If I have abstract class
public abstract class BaseClass<T>
where T: ISomeInterface
{ ... }
and two derived classes like
public class A : BaseClass<Model1>
{ ... }
public class B : BaseClass<Model2>
{ ... }
Is there a way to setup StrunctureMap to instantiate corresponded class by given model inherited from ISomeInterface with StructureMap?
public class static MyFactory
{
public static BaseClass<T> Get<T>()
where T: ISomeInterface
{
// StructureMap instantiates class here
...?
}
}
MyFactory.Get<Model1>(); // returns instance of A
MyFactory.Get<Model2>(); // returns instance of B
I want StructureMap configuration works well for any new such classes (like class C : BaseClass<Model3>) to be automatically recognized by StructureMap, without configuring additional interface->class mapping
What you are looking for is called batch-registration and this is how to do that in StructureMap:
var container = new Container(cfg =>
{
cfg.Scan(scanner =>
{
scanner.AssemblyContainingType(typeof(BaseClass<>));
scanner.WithDefaultConventions();
scanner.ConnectImplementationsToTypesClosing(typeof(BaseClass<>));
});
});
Related
Update
Well, I wasn't sure what I was asking for so it got a bit of an XY-question/discussion.
Main problem now is that I have an abstract base class which can be seen as a service, and sub services that derives from it (properties / abstract methods).
I've tried workarounds with using Interface, but no luck. I do not need the IOtherService in my Controller, so I don't want to inject it there.
Startup:
services.AddTransient<IMyBaseService, MyBaseService>();
Base service:
public MyBaseService(IOtherService other)
{
OtherService = other;
}
public MyBaseService()
{
// this runs
}
Derived service
public class DerivedService : MyBaseService
{
public DerivedService(string x)
{
}
public DoStuff()
{
OtherService.RunSomething();
}
}
I just need IOtherService to be injected in my Base service so my child "services" can use it from an inherited property.
Or is this an example of property injection?
Base class:
public abstract class Vehicle : ICleanVehicle
{
private readonly ICleanVehicle _cleanVehicle;
public Vehicle(ICleanVehicle cleanVehicle)
{
if (cleanVehicle == null) throw new ArgumentNullException("cleanVehicle");
_cleanVehicle = cleanVehicle;
}
}
Derived class:
public class Car : Vehicle
{
private readonly ICleanVehicle _cleanVehicle;
public Car(ICleanVehicle cleanVehicle) : base(cleanVehicle)
{
_cleanVehicle = cleanVehicle;
}
}
This way you have one single constructor defining the dependencies that the derived classes require. The derived classes will then call the constructor of the base class.
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'm trying to figure out if this is possible:
public abstract class A<T>
{
public void MyFunc() { ... }
}
public MyClass : A<string>
{
}
Is there a way for MyFunc to know that it has been instanced in a clas of type MyClass ?
I think I need to clarify the question some more:
I have a generic abstract class that contains some core functionality accessed through a singleton.
The user is building a derived class to extend functionalities but the class is not instantiated through a new, but rather by the singleton, contained in the A class once it is accessed.
So, you could see the flow as such:
In the beginning, there is the abstract A<T>
The user creates MyClass : A<string>
The user now accesses: MyClass.MyFunc()
The singleton in MyFunc is then creating the instance
The singleton code is as follows:
public abstract class Singleton<T> where T : class
{
private static readonly Lazy<T> _Instance = new Lazy<T>(CreateInstanceOfT);
protected static T Instance => _Instance.Value;
private static T CreateInstanceOfT()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
}
so:
class A<T>
is really:
class A<T> : Singleton<A>
but what I really need is to, somehow, make it like
Singleton<MyClass>
or whatever class is deriving from
A<T>
I hope this clarifies the question.
Yes, you could do something like:
public abstract class A<T>
{
public void MyFunc()
{
if(this.GetType() == typeof(MyClass))
{
// do your magic
}
}
}
public class MyClass : A<string>
{
}
but why?
Seems to me, if I read your question right, that if the instance of A needs to have MyFunc act differently when it is a MyClass, then MyFunc should be virtual, and overridden in MyClass.
public abstract class A<T>
{
public virtual void MyFunc() { ... }
}
public MyClass : A<string>
{
public override void MyFunc() { ... }
}
I have an assembly with a lot of classes (300+) with a BaseClass and I want register a generic class with a interface.
With unity you have to register by {Name} if you want to resolve an array of objects of the interface.
I want an array of objects in the MainViewModel automatically.
Is there a way to automate this with reflection?
Any suggestions?
Example (pseudo):
public class BaseClass
{
public void doFoo();
}
public ClassNumber001 : BaseClass
{
}
public ClassNumber002 : BaseClass
{
}
public interface ISuperman
{
}
public class Superman : ISuperman where T : BaseClass
{
}
public MainViewModel(IEnumerable<ISuperman> lotsofSuperman)
{
}
Working example by hand:
container.RegisterType<ISuperman, Superman <ClassNumber001>>("ClassNumber001");
container.RegisterType<ISuperman, Superman <ClassNumber002>>("ClassNumber002");
container.RegisterType<IEnumerable<ISuperman>, ISuperman[]>();
This is something that comes to my mind that might work for you...
You can register the type as follows, and should work for the open generic.
container.RegisterType(typeof(ISuperman<>), typeof(Superman<>), ... );
Registering generic parameters and types
Hope this helps!
Yes, you'll need to use reflection to easily create all of the mappings that you want. Since you are using Unity 3 you can take advantage of Registration by Convention to provide help (with the heavier lifting) in registering the classes.
I've taken your pseudo code and translated it into real code:
public abstract class BaseClass
{
public abstract void DoFoo();
}
public class ClassNumber001 : BaseClass
{
public override void DoFoo()
{
Console.WriteLine("001 Foo");
}
}
public class ClassNumber002 : BaseClass
{
public override void DoFoo()
{
Console.WriteLine("002 Foo");
}
}
public interface ISuperman
{
void Do();
}
public class Superman<T> : ISuperman where T : BaseClass
{
private T baseClass;
public Superman(T baseClass)
{
this.baseClass = baseClass;
}
public void Do()
{
this.baseClass.DoFoo();
}
}
public class MainViewModel
{
public MainViewModel(IEnumerable<ISuperman> lotsofSuperman)
{
foreach(ISuperman superman in lotsofSuperman)
{
superman.Do();
}
}
}
Then use registration by convention to register all the generics:
IUnityContainer container = new UnityContainer();
container.RegisterTypes(
AllClasses.FromAssembliesInBasePath().Where(t => typeof(BaseClass).IsAssignableFrom(t))
.Select(t => typeof(Superman<>).MakeGenericType(t)),
t => new Type[] { typeof(ISuperman) },
t => t.GetGenericArguments().First().Name,
WithLifetime.Transient);
container.RegisterType<IEnumerable<ISuperman>, ISuperman[]>();
container.Resolve<MainViewModel>();
In the above code we get all classes that inherit from BaseClass and then construct a type Superman<> and map that to ISuperman using the name of the BaseClass. The RegisterTypes call will be equivalent to calling RegisterType for every BaseClass:
container.RegisterType<ISuperman, Superman<ClassNumber001>("ClassNumber001");
container.RegisterType<ISuperman, Superman<ClassNumber002>("ClassNumber002");
Then when MainViewModel is resolved it iterates over all ISuperman instances and calls a method which prints out:
001 Foo
002 Foo
showing that we injected 2 ISuperman instances: Superman<ClassNumber001> and Superman<ClassNumber002>.
If you need specific registrations for the BaseClasses (e.g. non-default lifetime manager) then you can use registration by convention to register those too).
There are some of the ways this can be done. One is by using XML where the type is defined lets say MyClass and IMyClass and during runtime it resolves based on the assemblies available. But a better approach in my opinion would be to create a project to which you can delegate the responsibility of loading up the dependencies.
Lets say you create a class like so:
public class MyClass : IMyClass
{
private readonly IUnityContainer _container;
#ctor
// initialie the container through the constructor
public void DoWork<Interface, Class>() where Class: Interface
{
_container.RegisterType<Interface, Class>(
//TODO: You can setup the container lifecycle which can be transient
// or singleton or custom based on your project requirement
)
}
}
Now whoever needs to register itself can call this interface IMyClass to get itself registered in the container and dependency can be injected to whichever class needs to perform that task.
I have the following class:
public class ContentService : IContentService
I would like to make a BaseService class and implement some common functionality there. However I would also like to still implement all the IContentService methods.
How can I modify this line so it both implements the interface and inherits from BaseService?
public class ContentService: BaseService, IContentService
{
}
You can add as many interfaces as you want, and up to one base class in the list. Just use a comma to separate each additional interface.
The base class doesn't need to be the first item in the list, either.
You can inherit your class from both base class and interface. Implementing interface in base class provides you with option to not implement all the interface methods. Like following example:
interface ITestInterface
{
void Test();
string Test2();
}
public class TestBase : ITestInterface
{
#region ITestInterface Members
public void Test()
{
System.Console.WriteLine("Feed");
}
public string Test2()
{
return "Feed";
}
#endregion
}
public class TestChild : TestBAse, ITestInterface
{
public void Test()
{
System.Console.WriteLine("Feed1");
}
}
public static void Main(){
TestChild f = new TestChild();
f.Test();
var i = f as ITestInterface;
i.Test();
i.Test2();//not implemented in child but called from base.
}
public class ContentService: BaseService, IContentService
Will inherit from BaseService and implement your IContentService interface.
You may also want to look up Abstract classes/methods for your base class.