UPDATE: Should I try to handle it by DI container or it's a wrong abstraction level here?
I would like to implement ABSTRACT FACTORY using MEF (.NET 4.5).
It doesn't work for me...
The composition remains unchanged. The changes were rejected because of the following error(s):
The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint:
ContractName Mef3.Factory
RequiredTypeIdentity Mef3.Factory
Resulting in: Cannot set import 'Mef3.Program._factory (ContractName="Mef3.Factory")' on part 'Mef3.Program'.
Element: Mef3.Program._factory (ContractName="Mef3.Factory") -->
Mef3.Program
Is it the right way to do it in MEF?
How can I forward id to Foo/Bar ctors?
The code:
class Program
{
static void Main(string[] args)
{
var program = new Program();
program.Run();
}
readonly CompositionContainer _container;
public Program()
{
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
_container = new CompositionContainer(catalog);
_container.ComposeParts(this);
}
[Import]
public Factory _factory;
public void Run()
{
var foo = _factory.GetInstance("foo", 123);
Console.WriteLine(foo is Foo);
}
}
[Export]
public class Factory
{
private readonly ExportFactory<Foo> _fooFactory;
private readonly ExportFactory<Bar> _barFactory;
[ImportingConstructor]
public Factory(ExportFactory<Foo> fooFactory, ExportFactory<Bar> barFactory)
{
_fooFactory = fooFactory;
_barFactory = barFactory;
}
public Base GetInstance(string name, int id)
{
switch (name)
{
case "foo":
return _fooFactory.CreateExport().Value;
case "bar":
return _barFactory.CreateExport().Value;
}
throw new ArgumentException();
}
}
public class Foo : Base
{
[ImportingConstructor]
public Foo([Import("Id")] int id)
{
}
}
public class Bar : Base
{
[ImportingConstructor]
public Bar([Import("Id")] int id)
{
}
}
[InheritedExport]
public abstract class Base
{
}
The issue looks to be caused by your [Import("Id")] on Foo and Bar. There is no export with a contract name of "Id". MEF in general doesn't allow you to pass in imports at runtime, you need to be able to satisfy the entire graph at composition time or else it will not work. If you wanted to use MEF to accomplish this particular scenario you should remove the ImportingConstructor on Foo and Bar and add a SetId method on the Base class and have your factory call it when you call GetInstance.
Related
In a .NET Core 3.1 console application I want a Class that would have some parameters in constructor injected but some that I could assign manually. For example something like that but with IConfiguration Injected:
static void Main() {
var myObj1 = new MyClass(1);
var myObj2 = new MyClass(2);
}
public class MyClass {
public MyClass(IConfiguraiton config, int myVal)
{
}
}
I tried this with Ninject:
static void Main()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Get<MyClass>();
}
public class MyClass
{
public MyClass(IConfiguraiton config)
{
}
}
public class Bindings : NinjectModule
{
public override void Load()
{
var configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();
Bind<IConfiguration>().ToMethod(ctx => SetupConfiguration()).InSingletonScope();
Bind<MyClass>().ToSelf().InTransientScope();
}
}
I managed to make simple dependency injection, but haven't had any success making injection with parameters.
I've read a lot of people suggesting that it's better to pass parameters into methods of the class rather than constructor, however in my situation this isn't an option in addition I'm a software engineering student, and would like to learn how to do this, since it might be useful in some situations.
This is a situation where the Ninject.Extensions.Factory is useful, as it is made exactly for this situation. It does pull in the Factory dependency in addition to Castle.Core, as it uses DynamicProxy under the hood (as a SE student, playing with this library is a good idea for using the interceptor pattern).
To use it, you define a Factory interface like so:
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
Note that the Create method returns MyClass, and the argument(s) to the Create method match exactly in type and name to the arguments you wish to provide. The argument type(s) you want injected must be registered with the kernel. Unfortunately, it is easy to make a mistake here - if you specify a parameter that does not exist in the factory interface it is ignored, but if you forget one it will throw an exception when called.
Next, register IMyClassFactory like this: Bind<IMyClassFactory>().ToFactory(); and remove your binding for MyClass. Then wherever you need to create an instance, inject IMyClassFactory and call Create: kernel.Get<IMyClassFactory>().Create(2)
You can achieve the same result without using Ninject.Extensions.Factory by writing and registering your own implementation of IMyClassFactory, essentially doing the same thing that the code the Factory extension ends up emitting. A full sample is below using both methods based on commenting in/out the registration (note the output if you add .InSingletonScope() to the registration of IConfiguraiton - both approaches respect the binding scopes of Ninject).
internal class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IConfiguraiton>().To<Configuraiton>();
kernel.Bind<IMyClassFactory>().ToFactory();
//kernel.Bind<IMyClassFactory>().To<NinjectMyClassFactory>().InSingletonScope();
var factory = kernel.Get<IMyClassFactory>();
var one = factory.Create(1);
var two = factory.Create(2);
}
}
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
public class NinjectMyClassFactory : IMyClassFactory
{
public NinjectMyClassFactory(IResolutionRoot resolutionRoot)
{
ResolutionRoot = resolutionRoot;
}
private IResolutionRoot ResolutionRoot { get; }
public MyClass Create(int myVal)
{
return ResolutionRoot.Get<MyClass>(new ConstructorArgument("myVal", myVal));
}
}
public class MyClass
{
public MyClass(IConfiguraiton config, int myVal)
{
Console.Out.WriteLine("Created MyClass({0},{1})", config.MyNum, myVal);
}
}
public interface IConfiguraiton { int MyNum { get; } }
public class Configuraiton : IConfiguraiton
{
static int CreateCount;
public Configuraiton()
{
MyNum = Interlocked.Increment(ref CreateCount);
}
public int MyNum { get; }
}
I only know basics of IoC. For the sake of simplicity (uhh), I want to stay with Microsoft.Extensions.DependencyInjection.
The IProcessor interface (and IData one which I don't detail and is implemented by Excel and SQLServer classes):
public interface IProcessor
{
List<FielModel> ReadFieldsFromExcel();
List<FieldModel> ReadFieldsFromSQLServer();
}
The Processor implementation:
public class Processor : IProcessor
{
private readonly IData _excel;
private readonly IData _sqlServer;
public Processor(IData excel, IData sqlServer)
{
_excel = excel;
_sqlServer = sqlServer;
}
public List<FielModel> ReadFieldsFromExcel();
{
// ..
}
public List<FieldModel> ReadFieldsFromSQLServer();
{
// ..
}
}
The main Program with the DI.
class Program
{
private static ServiceProvider _serviceProvider;
static void Main(string[] args)
{
RegisterServices();
var processor = _serviceProvider.GetService<IProcessor>();
// ..
}
private static void RegisterServices()
{
// Setups dependency injection
var service = new ServiceCollection()
.AddSingleton<IProcessor, Processor>()
.AddSingleton<IData, Excel>()
.AddSingleton<IData, SQLServer>()
.AddSingleton<Program>();
_serviceProvider = service.BuildServiceProvider();
}
}
The problem is that both excel and slqServer are instantiated to SQLServer (ie the last IData registered singleton). How can I resolve this instatiation via dependency injection?
I already found a way to instantiate specific class the following way, but I don't think it is directly (and implicitly) applicable to a class constructor...
var excel = _serviceProvider.GetServices<IData>()
.First(o => o.GetType() == typeof(Excel));
Thanks for any insights.
You could register a delegate:
var service = new ServiceCollection()
.AddSingleton<Excel>()
.AddSingleton<SQLServer>()
.AddSingleton<IProcessor>(provider =>
new Processor(
provider.GetRequiredService<Excel>(),
provider.GetRequiredService<SQLServer>())
.AddSingleton<Program>();
The simplest way is to declare a marker interface for each specific implementation:
public interface IExcelData : IData { /* nothing */ }
public class Excel : IExcelData { ... }
public interface ISqlServerData : IData { /* nothing */ }
public class SqlServer : ISqlServerData { ... }
public class Processor : IProcessor
{
private readonly IData _excel;
private readonly IData _sqlServer;
public Processor(IExcelData excel, ISqlServerData sqlServer)
{
_excel = excel;
_sqlServer = sqlServer;
}
...
}
services
.AddSingleton<IExcelData, Excel>()
.AddSingleton<ISqlServerData, SQLServer>()
...
BTW, instead of manually creating the dependency containers, you should look into using the generic host: https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host
You could also inject an IEnumerable<YourDependency> if the two concrete types are registered against the same interface.
public class Processor : IProcessor
{
private readonly IEnumerable<IData> _dataDependencies;
public Processor(IEnumerable<IData> dataDependencies)
{
_dataDependencies= dataDependencies;
}
}
You could then resolve the relevant type by having some sort of Enum on the implementing class that you can use to select the appropriate service. I will use a simple string example to illustrate. (you probably shouldn't do it this way)
public class Processor : IProcessor
{
private readonly IEnumerable<IData> _dataDependencies;
public Processor(IEnumerable<IData> dataDependencies)
{
var selectedDependency = dataDependencies.FirstOrDefault(dep => dep.Type == "Excel");
}
}
Please try this.
var excel = _serviceProvider.GetServices<Excel.IData>();
After reading comment .
You can change constructor as following.
public Processor(Excel.IData excel, SQLServer.IData sqlServer)
{
_excel = excel;
_sqlServer = sqlServer;
}
We are building an application where we have to have both old and new version to work side by side (V1 is old and V2 is new). Now to handle new flow we are using same old interfaces with everything being the same and differs only in functionality, hence now we have to define a named instance in-order to resolve the instances for new flow.
In the process teams have started using Service Factory Pattern as shown below
class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IServiceFactory serviceFactory)
{
_dataManager = serviceFactory.GetInstance<IDataManager>();
}
public void Execute()
{
_dataManager.Run();
}
}
Service Factory Class
public class ServiceFactory : IServiceFactory
{
private readonly IFeatureEvaluator _featureEvaluator;
public ServiceFactory(IFeatureEvaluator featureEvaluator)
{
_featureEvaluator = featureEvaluator;
}
public T GetInstance<T>()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
return ObjectFactory.GetInstance<T>("V2")
}
return ObjectFactory.GetInstance<T>();
}
}
Since Service Factory is anti-pattern and also it creates lot of complexities in retiring the old flow in future, I would want a way to initialize the dependencies at the container(structuremap ioc) itself or to work in a "Pure DI" way so that we can avoid headache. Any idea on how to tackle this.
Update:
IDataManager Implementation
public interface IDataManager
{
void Run();
}
public class OldFlow : IDataManager
{
public void Run()
{
//
}
}
public class NewFlow : IDataManager
{
public void Run()
{
//
}
}
IDataManager has 2 implementations and resolving the instance should be based on _featureEvaluator, if V2 flow then "newflow" should be instantiated else "old flow" instance
Why don't you just inject the dependency you need?
public class DataProcessor
{
private readonly IDataManager _dataManager;
public DataProcessor(IDataManager dataManager)
{
_dataManager = dataManager;
}
public void Execute()
{
_dataManager.Run();
}
}
In your Composition Root you can conditionally compose DataProcessor with the implementation of IDataManager you'd like:
public DataProcessor CreateDataProcessor()
{
if (_featureEvaluator.IsEnabled<"V2">())
{
IDataManager dm = new NewFlow();
return new DataProcessor(dm);
}
IDataManager dm = new OldFlow();
return new DataProcessor(dm);
}
This seems to be similar to feature toggles. Why, by the way, is _featureEvaluator an interface? Wouldn't a bool suffice?
My configuration for a calculator dependent on its' View (GUI) is defined like so (it is then Resolved in the current context):
Dependencies.register<IView, View>(
"standardView"
);
//Register: calculator release configuration
Dependencies.register<ICalculator, Calculator>(
"releaseCalculator",
(new InjectionProperty(
"IView",
Dependencies.resolve<IView>("standardView")
))
);
//Resolve:
Calculator theCalculator = (Calculator)Dependencies.resolve<ICalculator>(
"releaseCalculator"
);
Where Dependencies is a wrapper for an IUnityContainer.
The injection-point in Calculator is:
private IView view;
[Dependency]
public IView IView{
get{return view;}
set{view = value;}
}
If you wish to see the definition for Dependencies please note that it is absolutely equivalent to a projection of unity container except I have extended direct control on lifetime-managers.
The problem is simply; given the above setup, the Property IView resolves to null at run-time. It is simply as though Unity just doesn't bloody work.
#Haukinger here is the wrapper:
using System.Collections.Generic;
using Unity;
using Unity.Lifetime;
using Unity.Registration;
namespace Calculator.Utils
{
public static class Dependencies
{
private static IUnityContainer graph;
private static List<KeyValuePair<string, LifetimeManager>> lifetimeManagers;
static Dependencies(){
//container
graph = new UnityContainer();
//instance managers 1 per dependency instance (implementor)
lifetimeManagers = new List<KeyValuePair<string, LifetimeManager>>();
}
//STATES:
public static void register<I, P>(string alias, params InjectionMember[] injections)
{
ContainerControlledTransientManager newLM = new ContainerControlledTransientManager();
lifetimeManagers.Add(new KeyValuePair<string, LifetimeManager>(
alias,
newLM
));
graph.RegisterType(
typeof(I),
typeof(P),
alias,
newLM,
injections
);
}
//function is identitical to Resolve
public static T resolve<T>(string alias)
{
return (T)graph.Resolve(typeof(T), alias);
}
public static void dispose(string alias)
{
LifetimeManager target = (ContainerControlledTransientManager)lifetimeManagers.Find((elem)=>(elem.Key.Equals(alias))).Value;
target.Dispose();
}
}
}
Named registrations are only injected when you request all registered types, i.e. IView[] allViews. If you request only one instance, you'll receive the default registration, in your case just null as you have no default registration.
Remove the name (standardView) and pass null as parameter name to RegisterType and you're good to go.
EDIT: this code works fine at my machine
internal class Program
{
static void Main( string[] args )
{
var container = new UnityContainer();
container.RegisterType<IDependency, MyDependency>((string)null);
var resolved = container.Resolve<Consumer>();
// resolved.Dependency is an instance of MyDependency
}
}
internal class Consumer
{
[Dependency]
public IDependency Dependency { get; set; }
}
public interface IDependency
{
}
internal class MyDependency : IDependency
{
}
I have to write a Complex calculator logic which has 4 different components to be calculated brokerage, stockprice, admin charges & other charges. Each having a different logic and formulas.
So I decided to use Unity DI. I have a ContainerFactoryClass which resolves all classes which implements IChargeCalculator interface as shown below in the TotalAnnualCostCalculator constructor.
public class TotalAnnualCostCalculator
{
private readonly IUnityContainer container;
//Constructor
public TotalAnnualCostCalculator()
{
container = ContainerFactory.InitializeContainer();
ContainerFactory.SetupContainer(container);
}
public AnnualCostCharges CalculateTotalAnnualCost(Parameters product)
{
var calculators = container.ResolveAll<ICalculator>().ToList();
// Invoke calcualtion method
Parallel.ForEach(calculators, c =>
{
return c.CalculateAnnualCost(product);
});
}
}
Container Factory class:-
public static class ContainerFactory
{
public static IUnityContainer Container { get; private set; }
public static IUnityContainer InitializeContainer()
{
var container = new UnityContainer();
RegisterDependencies(container);
return container;
}
private static void RegisterDependencies(UnityContainer container)
{
container.RegisterType<ICalculatorStrategyFactory, CalculatorStrategyFactory>("Factory");
container.RegisterType<IEffectiveAnnualCostCalculator, InvestmentManagementChargeCalculator>("IMCChargeCalculator",
new InjectionConstructor(new ResolvedParameter<ICalculatorStrategyFactory>("Factory")));
//container.RegisterType<IEffectiveAnnualCostCalculator, AdministrationChargeCalculator>("AdministrationChargeCalculator");
container.RegisterType<IEffectiveAnnualCostCalculator, AdviceChargeCalculator>("AdviceChargeCalculator");
container.RegisterType<IEffectiveAnnualCostCalculator, OtherChargeCalculator>("OtherChargeCalculator");
container.RegisterType<IInvestmentManagementChargeCalculator, LumpSumIMCCalculator>("LumpSumIMCCalculator");
container.RegisterType<IInvestmentManagementChargeCalculator, DebitOrderIMCCalculator>("DebitOrderIMCCalculator");
}
public static void SetupContainer(IUnityContainer container)
{
Container = container;
}
}
Then any API consumes my Calculator.dll by just creating an instance of TotalAnnualCostCalculator and call a method like this.
var totalCharges = calc.CalculateTotalAnnualCost(prod);
My code reviewer says its better to use Factory Pattern ,as this tightly coupled to Unity Framework.
Please advise
Indeed, don't use a DI Container at all. As Steven suggests in the comments, this seems a great fit for a Composite:
public class TotalAnnualCostCalculator : ICalculator
{
private readonly ICalculator[] calculators;
public TotalAnnualCostCalculator(params ICalculator[] calculators)
{
this.calculators = calculators;
}
public AnnualCostCharges CalculateTotalAnnualCost(Parameters product)
{
Parallel.ForEach(this.calculators, c => c.CalculateAnnualCost(product));
}
}
In the Composition Root, then, you simply new up all the ICalculator objects you'd like to use, and pass them to the constructor of TotalAnnualCostCalculator.
Register all IEffectiveAnnualCostCalculator (or what ever interface).
You just need to map the enumerable to an array of the same type.
container.RegisterType<IEnumerable<IEffectiveAnnualCostCalculator>, IEffectiveAnnualCostCalculator[]>();
Resolve with dependency injection:
private IEnumerable<IEffectiveAnnualCostCalculator> calculators;
public TotalAnnualCostCalculator(IEnumerable<IEffectiveAnnualCostCalculator> calculators)
{
this.calculators = calculators;
}
public AnnualCostCharges CalculateTotalAnnualCost(Parameters product)
{
Parallel.ForEach(this.calculators, c => c.CalculateAnnualCost(product));
}