I have the following class
public class AbstractJobDao<T> where T : IJob {
protected T buildJob() {
// create an IJob implementation instance based on the generic parameter
}
}
public class FullTimeJobDao : AbstractJobDao<FullTimeJob> {
}
public class InternshipDao : AbstractJobDao<Internship> {
}
Both FullTimeJob and Internship implement the IJob interface. I'd like the buildJob() method to be able to infer the generic in the Dao implementation class using reflection, and then create an instance of that type. Is there a way to do this using reflection in .NET 3.5?
If so, what should the line/lines of code look like in the buildJob() method?
EDIT -- I think I'm not clear on my question. What I want is for when buildJob() is called inside of the FullTimeJobDao, to create an instance of FullTimeJob. When buildJob() is called from inside of InternshipDao, it should create an instance of Internship, based on the generic type as defined at the top of the class.
What you have should almost work, except you don't require your generic argument to be instantiable. If you add that as a constraint, you should be able to use new:
public class AbstractJobDao<T> where T : IJob, new() {
protected T buildJob() {
return new T();
}
}
Alternatively, if you have some reason why that constraint is not appropriate in your situation, you can use Activator.CreateInstance:
public class AbstractJobDao<T> where T : IJob {
protected T buildJob() {
return Activator.CreateInstance<T>();
}
}
You have to declare your AbstractJobDao class this way :
public class AbstractJobDao<T> where T : IJob, new() {
protected T buildJob() {
return new T();
}
}
Note the new() after IJob : this way, you're indicating that parameter T :
Implements IJob's methods
Offers a constructor with no argument.
So the compiler will allow you to use new T().
You can create IJob factory to implement it
interface IJobFactory
{
IJob Create();
}
class FullTimeJobFactory
: IJobFactory
{
IJob Create()
{
return new FullTimeJob();
}
}
class InternshipJobFactory
: IJobFactory
{
IJob Create()
{
return new InternshipJob();
}
}
now you can use abstract factoy IJobFactory to create instancies of abstract IJob
public class AbstractJobDao<T> where T : IJob {
public AbstractJobDao(IJobFactory<T> factory)
{
}
protected IJobFactory<T> Factory{get;set;}
protected T buildJob() {
return Factory.Create();
}
}
public class FullTimeJobDao : AbstractJobDao<FullTimeJob> {
public FullTimeJobDao()
: base(new FullTimeJobFactory())
{}
}
public class InternshipDao : AbstractJobDao<Internship> {
public InternshipDao ()
: base(new InternshipJobFactory())
{}
}
Related
Using this generic base class:
public abstract class Logic<U> where U : class
{
protected U m_provider;
public Logic(U provider)
{
m_provider = provider;
}
}
I'm trying to create a base test class for unit test:
public class LogicBaseTest<T, U> where T : Logic <U>, new() where U: class
{
protected T m_logic;
protected U m_provider;
[OneTimeSetUp]
public virtual void OneTimeSetup()
{
m_provider = (U)Substitute.For<IInterface>();
m_logic = new T(m_provider);
}
}
It complains on the constructor, it requests for the new() constrain but when I add it then it complains that the constructor cannot take parameters.
I could add a method to populate the provider but I'm wondering whether it could be done in the constructor.
So you have two problems here:
LogicBaseTest needs to know how to instantiate a Logic<U>.
Logic<U> requires a U in the constructor.
My proposed solution to it is to pass a factory delegate into the base test class and remove the new() requirement. Then your setup can construct the Logic class using the factory:
public class LogicBaseTest<T, U>
where T : Logic<U>
where U: class
{
protected readonly Func<U, T> _factory;
public LogicBaseTest(Func<U, T> factory)
{
_factory = factory;
}
[OneTimeSetUp]
public virtual void OneTimeSetup()
{
m_provider = (U)Substitute.For<IInterface>();
m_logic = _factory(m_provider);
}
}
In the derived test class you just have to tell the base class how to new up a Logic<U>:
public class DerivedTest : LogicBaseTest<Logic<MyUType>, MyUType>
{
public DerivedTest()
: this(u => new Logic<MyUType>(u))
{
}
}
Let's break down your generic constraint into plain English
where T : Logic<U>, new()
This means
The type of T needs to inherit from Logic, the generic type parameter must be U and have a public, parameterless, constructor
But the problem is that Logic by itself already breaks that constraint. Now, how do we fix this? There are multiple ways
Use a "factory function" to instantiate your m_logic alongside removing the new constraint (see DiplomacyNotWar's answer)
Remove the new() constraint and use something like Activator.CreateInstance instead to instantiate your Logic class
Add a parameterless constructor to Logic and configure your m_provider some other way
Move instantiation of m_logic into the unit test itself (maybe add a helper method if you need to create the same Logic for a ton of unit tests)
Research if your unit testing framework supports some form of Dependency Injection and inject everything you need
You cannot add a generic type constraint such as where T : new(U).
Instead, you can use a Factory.
public interface IFactory<out TObject, in TProvider>
{
public TObject Create(TProvider provider);
}
then use it in your base test
public class LogicBaseTest<T, U> where T : Logic <U> where U: class // remove new()
{
// fields
private readonly IFactory<T, U> _factory;
public LogicBaseTest(IFactory<T, U> factory)
{
_factory = factory;
}
[OneTimeSetUp]
public virtual void OneTimeSetup()
{
m_provider = (U)Substitute.For<IInterface>();
m_logic = _factory.Create(m_provider);
}
}
Example
public class Logic1Provider
{
}
public class Logic1Factory : IFactory<Logic1, Logic1Provider>
{
public Logic1 Create(Logic1Provider provider)
{
return new Logic1(provider);
}
}
public class Logic1 : Logic<Logic1Provider>
{
public Logic1(Logic1Provider provider) : base(provider)
{
}
public void DoDomeLogic()
{
// do stuff
}
}
var factory = new Logic1Factory();
var baseTest = new LogicBaseTest<Logic1, Logic1Provider>(factory);
How do I force all derived classes of an interface to have a constructor with a signature? This doesn't work:
public interface Constructor<T> where T : Constructor<T>, new()
{
Constructor(T);
}
public interface IParameters
{
}
public interface IRule : Constructor<IParameters>
{
//IRule (IParameters); must exist
}
You can't, not via an interface. But you can sort of get at it with an abstract class. Similar to what the accepted answer here describes, try:
public abstract class MustInitialize<T>
{
public MustInitialize(T parameters)
{
}
}
public class Rule : MustInitialize<IParameters>, IRule
{
IParameters _parameters;
public Rule(IParameters parameters)
: base (parameters)
{
_parameters= parameters;
}
}
You can't force a specific constructor signature.
Even with an abstract class as demonstrated in Mark's answer, you can only force the constructor of the abstract class, but nothing is stopping the author of the derived class to do something like this:
public class Rule : MustInitialize<IParameters>, IRule
{
public Rule()
: base (new Parameters())
{
// Assuming Parameters is a class that implements the IParameters interface
}
}
However, you can force dependency injection by using method (setter) injection:
public interface IMethodInjection<T>
{
void Method(T injected);
}
I think you can design your base class like the following example:
public abstract class MyBase
{
private MyBase()
{
}
public MyBase(string a)
{
}
}
public class MyDerived : MyBase
{
public MyDerived(string a) : base(a)
{
}
}
You can even delete the private constructor if its not needed
I have the following classes (some of them are in the PRISM framework and cannot be changed):
public abstract class NetworkEventBase<T> : CompositePresentationEvent<T> where T : NetworkEventPayload { }
public class NetworkEventPayload { }
public class TestEvent : NetworkEventBase<TestPayload> { }
public class TestPayload : NetworkEventPayload { }
// the following classes are PRISM classes:
public class CompositePresentationEvent<TPayload> : EventBase { }
public abstract class EventBase { }
Now I need to convert an instance of TestEvent to its base class NetworkEventBase inside a decorator for IEventAggregator. IEventAggregator looks like:
public interface IEventAggregator
{
TEventType GetEvent<TEventType>() where TEventType : EventBase, new();
}
Now in my decorator I try to convert like this:
public class MessageBusAdapterInjectorDecorator : IEventAggregator {
...
public TEventType GetEvent<TEventType>() where TEventType : EventBase, new()
{
var aggregatedEvent = this.eventAggregator.GetEvent<TEventType>();
var networkEvent = aggregatedEvent as NetworkEventBase<NetworkEventPayload>;
if (networkEvent != null)
{
networkEvent.MessageBusAdapter = this.messageBusAdapter;
}
return aggregatedEvent;
}
}
However, networkEvent is always null, even when the runtime type of aggregatedEvent is TestEvent.
You seem to hope that the class called NetworkEventBase<T> would be covariant in T. But generic classes can't be covariant in C# (generic interfaces can).
See other threads on this issue.
I have the following and at some point I need to create Failures for Validations. We suppose each type deriving from Validation has one and only one type deriving from Failure<T> where T is the aforementioned implementation of Validation.
As I have a growing number of implementations of Validation, I need to be able to instantiate the right type deriving from Failure<T>, and call the link method on it within a method that looks like
void recordFailureForValidation(Validation v) {
Type failureType = dict[v.GetType()];
Object failure = Activator.CreateInstance(failureType);
// how do I call failure.link(v) ?
}
At Runtime, a dictionary gives me the type deriving from Failure<T> given T.
I am able to instantiate Failure<T> (Failure1, Failure2, etc...), but I can't find how to call link on the public field reference of my newly created Failure instance (by making all uses that made sense to me of GetMethod, MakeGenericMethod, Invoke, etc...)
public class MyReferenceClass<T>
where T : Object, new() {
public void link(T arg) { ... }
}
public abstract class Failure<T>
where T : ValidationRule, new() {
...
public MyReferenceClass<T> reference;
...
}
public class Failure1 : Failure<Validation1> {
}
public class Failure2 : Failure<Validation2> {
}
public abstract class ValidationRule {
...
}
public class ValidationRule1 : ValidationRule {
...
}
public class ValidationRule2 : ValidationRule {
...
}
link is private since you do not specify a different accessibility. Make it public or internal:
public class MyReferenceClass<T>
where T : Object, new() {
public void link(T arg) { ... }
}
then you can call it from Failure<T> through the reference property:
public abstract class Failure<T>
where T : ValidationRule, new()
{
protected T Validation {get; set;};
public MyReferenceClass<T> reference;
}
public class Failure1 : Failure<Validation1>
{
public void Test()
{
this.reference.link(Validation);
}
}
Let Failures implement a non generic IFailure interface as well as a generic one in the same manner as IEnumerable and IEnumerable<T>
Create an abstract factory method within ValidationRule that has to be implemented by each concrete Validation
public ValidationRule1 : ValidationRule
{
public override IFailure ToFailure()
{
return new Failure1(this);
}
...
}
in my Silverlight 4 application I started creating and using some generics and now I stumbled upon the following problem:
In a non-generic class, I have a abstract method, that returns a generic class:
public abstract class DTO_Base()
{
public abstract ServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}
The generic class is defined in the following way:
public abstract class ServiceModelBase<RootNodeType> where RootNodeType : ServiceNodeBase
Naturally, from DTO_Base derived classes will have to override the CreateBusinessObject method:
public class DTO_Editor : DTO_Base
{
public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
{
// the object to return have to be of type ServiceModelEditor
// which is derived from ServiceModelBase<ServiceNodeEditor>
// public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>
// ServiceNodeEditor is derived from ServiceNodeBase
// public class ServiceNodeEditor : ServiceNodeBase
ServiceModelEditor target = new ServiceModelEditor()
...
Functions to populate the 'target'
...
return target;
}
}
The line return target; causes an error, stating that it isn't possible to implicitly convert the type ServiceModelEditor in ServiceModelBase<ServiceNodeBase>. Also, an explicit conversion via target as ServiceModelBase<ServiceNodeBase> doesn't work.
How would I have to implement this method to work?
Try this:
public interface IDTO<Node> where Node : ServiceNodeBase
{
ServiceModelBase<Node> CreateBusinessObject();
}
public abstract class DTO_Base<Model,Node> : IDTO<Node>
where Model : ServiceModelBase<Node>
where Node : ServiceNodeBase
{
public abstract Model CreateBusinessObject();
#region IDTO<Node> Members
ServiceModelBase<Node> IDTO<Node>.CreateBusinessObject()
{
return CreateBusinessObject();
}
#endregion
}
public class DTO_Editor : DTO_Base<ServiceModelEditor, ServiceNodeEditor>
{
public override ServiceModelEditor CreateBusinessObject()
{
// the object to return have to be of type ServiceModelEditor
// which is derived from ServiceModelBase<ServiceNodeEditor>
// public class ServiceModelEditor : ServiceModelBase<ServiceNodeEditor>
// ServiceNodeEditor is derived from ServiceNodeBase
// public class ServiceNodeEditor : ServiceNodeBase
ServiceModelEditor target = new ServiceModelEditor();
return target;
}
}
I have faced a similar problem before and the only thing reasonable to do is to make the core base class generic also. You can remove the Model generic parameter (and the interface) and it will look a little less scary, but you loose visibility on the functionality of ServiceModelEditor outside of the method.
As it is, you've got to return a ServiceModelBase<ServiceNodeBase>. One option is to make your base class generic:
public abstract class DtoBase<T> where T : RootNodeType
{
public abstract ServiceModelBase<T> CreateBusinessObject();
}
Then:
public class DtoEditor : DtoBase<ServiceNodeBase>
{
public override ServiceModelBase<ServiceNodeBase> CreateBusinessObject()
{
...
}
}
If you are using .Net 4.0 I suggest you use interfaces to define your ServiceModelBase and specify an out variance modifier on that interface generic type:
class ServiceNodeBase { }
class ServiceNodeEditor : ServiceNodeBase {/*implementation*/}
//
interface IServiceModelBase<out RootNodeType>
where RootNodeType : ServiceNodeBase {
}
class ServiceModelEditor : IServiceModelBase<ServiceNodeEditor> {
/*implementation*/
}
//
abstract class DTO_Base {
public abstract IServiceModelBase<ServiceNodeBase> CreateBusinessObject();
}
class DTO_Editor : DTO_Base {
public override IServiceModelBase<ServiceNodeBase> CreateBusinessObject() {
return new ServiceModelEditor();
}
}