I use Castle Windsor in my c# project for DI and I've this scenario:
public class Class1:IMyClass
{
public string Name{get{return "Class1";}}
public int Version {get; set;}
private string _description;
public Class1(string description)
{
this._description=description;
}
}
public class Class2:IMyClass
{
public string Name{get{return "Class2";}}
public int Version {get; set;}
private string _description;
public Class2(string description)
{
this._description=description;
}
}
I can register those classes by the common IMyClass interface but now I need a factory for create a determinated instance; something like this:
IMyClass _myClass= someClassFactory.GetByName("Class2", version=1, description="test");
Is there an example for a factory that resolves a component by name and inject properties and/or constructor values?
Absolutely right Cristiano. Here a bit more info.
No matter how you write your factory you will not be able to create component based on the Name property. The reason for this is that the property is only availble after creating the object, and the factory needs it before that.
Create a factory :
interface ISomeClassFactory
{
IMyClass GetById(string name, int version, string description);
}
and a selector (copied from: http://docs.castleproject.org/Windsor.Typed-Factory-Facility-interface-based-factories.ashx)
public class CustomTypedFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
if(method.Name == "GetById" && arguments.Length == 1 && arguments[0] is string)
{
return (string)arguments[0];
}
return base.GetComponentName(method, arguments);
}
}
And register these as follows:
Component.For<IMyClass>().ImplementedBy<Class1>().Named("Class1"),
Component.For<IMyClass>().ImplementedBy<Class2>().Named("Class2")
Component.For<IISomeClassFactory>().AsFactory(c=> new CustomTypedFactoryComponentSelector())
Also make sure to add the TypedFactoryFacility to the container.
Once again Typed factory is the solution.
Related
I want to use generic classes with strategy pattern along with dependency injection in Asp.net
Definition of interface and concrete class
public interface IPaymentMethod<T>
{
string Name { get; set }
}
public interface PaymentMethod<T> : IPaymentMethod<T> where T: class
{
public string Name { get; set; }
}
Startup.cs
services.AddScoped(typeof(IPaymentMethod<>), typeof(PaymentMethod<>));
In the application
public class PaymentResolver
{
public PaymentResolver(List<IPaymentMethod<????>> paymentMethods)
{ ... }
public IPaymentMethod Resolve(string name)
{
return _paymentMethods.FirstOrDefault(item => item.Name == name);
}
}
How can I get the collection of IPaymentMethod instances from the dependency injection? PaymentResolver.Resolve method doesn't seem to be correct.
What you are looking for is kind of conflict to your self. So basically, you want to get a service when you know the service name. Then, my question is if you know service name
_paymentResolver.GetPaymentMethod("CreditCard/DebitCard")
you must know service type as well
class Invoice
{
public Invoice(IPaymentMethod<CreditCard> cc, IPaymentMethod<DeditCard> dc) {}
}
So what stops you from using a type rather than a name? Not to mention that it offers you strongly type so you don't have a risk of mistype the name.
Hope this helps clear your mind.
I have a class named SomeRule that can be serialized in a XML format. The class uses an ISomeService that I would like to be injected via autofac.
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
private readonly ISomeService m_someService;
private SomeRule() { }
public SomeRule(ISomeService someService)
{
m_someService = someService;
}
public void DoSomething()
{
m_someService.DoStuff(Attribute1);
}
}
public interface ISomeService {
void DoStuff(string param);
}
public class SomeServiceImpl : ISomeService
{
public void DoStuff(string param) => // Do something with the stuff.
}
Now, my program receives an XML string that I would like to deserialize but also, at the same time, have autofac inject the dependency for me.
void Main()
{
string serializedRule =
"<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
"<SomeRule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"Attribute1=\"Huuuuuge\" " +
"Attribute2=\"Cofveve\" />";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SomeRule));
var stringBuilder = new StringBuilder(serializedRule);
var newRule = xmlSerializer.Deserialize(
new StringReader(stringBuilder.ToString())) as SomeRule;
// ISomeService was not injected yet. Is it possible?
}
I can make this work by calling the autofac container, get the registered implementation of the ISomeService interface and assign it to a public property of the SomeRule instance. I am looking for a better solution, one that would not require the class to have a public property.
Is there a way to automatically inject dependencies with XmlSerializer?
From a DI standpoint, having data-centric objects with constructors that accepts service dependencies is rather problematic, and should be prevented.
When practicing DI, we try to centralize the composition of our object graphs of application components (i.e. the classes that contain behavior and have dependencies of their own) to a centralized place in the application called the Composition Root.
A data-centric object that includes constructor dependencies, however, complicates this practice, since it either forces composition out of the Composition Root, or forces the addition of factory abstractions for the creation of these objects.
Instead, you should use one of following two alternatives:
Separate data and behavior. This means moving SomeRule's DoSomething method to a new class, that takes SomeRule as an argument in its public method(s). The constructor dependency will move to this new class as well.
Remove the constructor dependency of SomeRule and instead inject it into DoSomething using method injection.
Option 1 might look like this:
// SomeRule only contains data. Much simpler
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
}
// Moved behavior to new class. This class can be injected
// into consumers, as usual.
public class SomeRuleHandler : IRuleHandler<SomeRule>
{
private readonly ISomeService m_service;
// There's now just one constructor left
public SomeRuleHandler(ISomeService service)
{
m_service = service ?? throw new ArgumentNullException("service");
}
public void DoSomething(SomeRule rule)
{
m_service.DoStuff(rule.Attribute1);
}
}
With option 2, the result will be the following:
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 { get; set; }
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
// No more constructors. The dependency is supplied in the method,
// but *not* stored.
public void DoSomething(ISomeService service)
{
service.DoStuff(Attribute1);
}
}
Having this interface :
public interface FileManager {
string UploadFile(HttpPostedFileBase file);
string UploadFile(Uri uri);
}
my implementation will looks like :
public class FileManagerAzure : FileManager {
private FileParser parser;
FileManagerAzure(FileParser parser){
this.parser = parser; // Can this be a constructor injection??
}
public string UploadFile(HttpPostedFileBase file) {
return parser.Parse(file); // Should I Inject the parser here depending on type ??
}
public string UploadFile(Uri uri) {
return parser.Parse(uri);
}
}
this have a dependency on FileParser which looks like following :
public interface FileParser {
string Parse(object source)
}
and ideally I would like to have some parsers implementations (this doesn't work of course) :
public class FileParserHttpPostedFileBase : FileParser {
string Parse(HttpPostedFileBase source) {
return file.FileName;
}
}
public class FileParserUri : FileParser {
string Parse(Uri source) {
return Uri.ToString();
}
}
Is there anyway to create the concrete parser dependency depending on the parameter passed to UploadFile() ? this have to be a setter injection ? Is this good, or are any other strategy I can follow ?
I have to make my FileParser interface receive an object as source. This doesn't sound like it should since I have a limited set allowed input types, certainly not object. In this case HttpPostedFileBase and Uri. How can I limit the scope for this ?
You can inject the dependencies via the constructor. That's the way I'd choose whenever possible. That means you can't use an IoC container for instantiation, though. You can use an abstract factory pattern to encapsulate the decision making of what concrete parser to inject, and have an IoC container inject the concrete factory into the calling class(es).
Seems like overkill, though. Since your FileManager interface exposes methods for both argument types why not inject both parser types? I'd make the FileParser type generic for that, so you don't need a new interface for every new parser.
public interface FileParser<T>
{
string Parse(T value);
}
public class UriParser : FileParser<Uri>
{
string Parse(Uri value)
{
// implementation
}
}
You could implement the FileManagerAzure like this then:
public class FileManagerAzure : FileManager {
private FileParser<Uri> uriParser;
private FileParser<HttpPostedFileBase> postedFileParser;
FileManagerAzure(FileParser<Uri> uriParser, FileParser<HttpPostedFileBase> postedFileParser){
this.uriParser = uriParser;
this.postedFileParser = postedFileParser;
}
public string UploadFile(HttpPostedFileBase file) {
return this.postedFileParser.Parse(file);
}
public string UploadFile(Uri uri) {
return this.uriParser.Parse(uri);
}
}
This implementation can be instantiated by an IoC container no problem too.
I think you should use generic typing:
public interface FileParser<T> {
string Parse(T source)
}
This way you can easily have multiple implementations as follows:
public class FileParserHttpPostedFileBase : FileParser<HttpPostedFileBase> {
public string Parse(HttpPostedFileBase source) {
return file.FileName;
}
}
public class FileParserUri : FileParser<Uri> {
public string Parse(Uri source) {
return Uri.ToString();
}
}
And this way you remove the ambiguity in your design because now it becomes clear what to inject into the constructor:
public class FileManagerAzure : FileManager {
private FileParser<HttpPostedFileBase> httpParser;
private FileParser<Uri> uriParser;
FileManagerAzure(FileParser<HttpPostedFileBase> httpParser,
FileParser<Uri> uriParser){
this.httpParser = httpParser;
this.uriParser = uriParser;
}
public string UploadFile(HttpPostedFileBase file) {
return httpParser.Parse(file);
}
public string UploadFile(Uri uri) {
return uriParser.Parse(uri);
}
}
However, if the FileManagerAzure only delegates to its dependencies like this, you should question whether the FileManager abstraction has any use. A consumer of the FileManager could depend directly on one of the FileParser<T> abstractions. And if the FileParser<T> only has that one line of code, we could even argue that you might even want to do without that abstraction (however, as always: your mileage may vary).
I have an interface:
public interface IInterface
{
string Get(obj o);
}
and I have the 2 classes:
public class C1 : IInterface
{
string Get(obj o);
}
public class C2 : IInterface
{
string Get(obj o);
}
I'd like to send in o and then have Ninject determine which interface it is based on the property of o. Obj being something like:
public class obj
{
public string Name {get;set;}
public int Id {get;set;}
}
I'd like something that's like:
Bind<IInterface>().To<C1>.When(obj.Name == "C1");
Bind<IInterface>().To<C2>.When(obj.Name == "C2");
but I haven't worked with Ninject before. Any ideas?
I've been somewhat liberal with the interpretation of your question, because i think you've skipped some "thinking steps" and necessary information.
However, what I recommend is doing it like this:
public interface INamed
{
string Name { get; }
}
public interface IFactory
{
IInterface Create(INamed obj);
}
public class Factory : IFactory
{
private readonly IResolutionRoot resolutionRoot;
public Factory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IInterface Create(INamed obj)
{
return this.resolutionRoot.Get<IInterface>(obj.Name);
}
}
Alternative: you could also use the ninject factory extension. Sadly enough it does not support named bindings by default, but you can customize it do so like documented here.
However to be perfectly frank i would rather go for manually implementing the factory, because it is more easily understandable. If i would be customizing the factory - which i have done - i would consider adding support for attributes (which specify how to handle a factory method parameter) instead of having to configure each .ToFactory() binding how it will interpret parameters.
Can Castle Windsor resolve a collection filtered by a string parameter?
interface IViewFactory
{
IView[] GetAllViewsInRegion(string regionName);
}
My application defines regions as groups of IView-derived types. When I display a particular region at runtime, I want to resolve an instance of every IView type within it (a la Prism).
I've tried doing it with the Castle's Typed Factory Facility, ComponentModel Construction Contributors, and Handler Selectors, but I can't figure out how to map multiple types to a string in a way that Castle can access, nor how to extend Castle to check the string when it decides which types to try to resolve and return in the container.
Is selection by string strictly necessary? Would it be possible to instead have all IView implementations in the same "region" implement a dedicated interface that derives from IView? Then you could use WindsorContainer.ResolveAll() (passing your region-specific IView as T) to resolve the implementations for the region in question (or you could use one of the Collection Resolvers to perform constructor injection).
In general, when trying to do things like this with Windsor, I make every effort to use the type system (and Windsor's support thereof) before resorting to string-based solutions.
Update: since we confirmed that selection by string is necessary in this case, the best solution I see is to simply inspect the list of handlers in the kernel that satisfy the IView service, then filter for the implementers where the region (defined via attribute) matches what we want, then resolve those implementers. This feels a bit hackish, but if you're okay with having a direct reference to the container in your IViewFactory implementation, this appears to work fine. Below is a passing test case demonstrating the solution.
[Test]
public void Test()
{
using (var factory = new ViewFactory())
{
var regionOneViews = factory.GetAllViewsInRegion("One");
Assert.That(regionOneViews, Is.Not.Null);
Assert.That(regionOneViews, Has.Length.EqualTo(2));
Assert.That(regionOneViews, Has.Some.TypeOf<RegionOneA>());
Assert.That(regionOneViews, Has.Some.TypeOf<RegionOneB>());
var regionTwoViews = factory.GetAllViewsInRegion("Two");
Assert.That(regionTwoViews, Is.Not.Null);
Assert.That(regionTwoViews, Has.Length.EqualTo(1));
Assert.That(regionTwoViews, Has.Some.TypeOf<RegionTwoA>());
}
}
}
public interface IViewFactory
{
IView[] GetAllViewsInRegion(string regionName);
}
public class ViewFactory : IViewFactory, IDisposable
{
private readonly WindsorContainer _container;
public ViewFactory()
{
_container = new WindsorContainer();
_container.Register(
Component.For<IView>().ImplementedBy<RegionOneA>(),
Component.For<IView>().ImplementedBy<RegionOneB>(),
Component.For<IView>().ImplementedBy<RegionTwoA>()
);
}
public IView[] GetAllViewsInRegion(string regionName)
{
return _container.Kernel.GetHandlers(typeof (IView))
.Where(h => IsInRegion(h.ComponentModel.Implementation, regionName))
.Select(h => _container.Kernel.Resolve(h.ComponentModel.Name, typeof (IView)) as IView)
.ToArray();
}
private bool IsInRegion(Type implementation,
string regionName)
{
var attr =
implementation.GetCustomAttributes(typeof (RegionAttribute), false).SingleOrDefault() as RegionAttribute;
return attr != null && attr.Name == regionName;
}
public void Dispose()
{
_container.Dispose();
}
}
public interface IView {}
[Region("One")]
public class RegionOneA : IView {}
[Region("One")]
public class RegionOneB : IView {}
[Region("Two")]
public class RegionTwoA : IView {}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RegionAttribute : Attribute
{
private readonly string _name;
public RegionAttribute(string name)
{
_name = name;
}
public string Name
{
get { return _name; }
}
}