Unity parameter constructor exception - c#

Within the bootstrapper class of my WebApi I'm trying to register a new instance of a class called 'Facade' based on its interface type.
Within this type being regitered it requires a new instance of 'CRUDOperator' which also has a new instance of 'Adaptor' in its constructor. Is what I'm trying to do possible? I am currently just recieving an exception that the overload params are incorrect.
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
*****ERROR*****
container.RegisterType<IFacade,Facade>(new CRUDOperatorSelector(new Adapter()));
return container;
}
}

Unity is capable of resolving concrete types without registering them, so if in Your case the types CRUDOperatorSelector and Adapter are concrete types (and I'm assuming they are) you just have to register the type Facade as implementation of IFacade and resolve it. Unity will then create an instance of each dependency and pass it to the constructor of Facade.
If some of those types implement an abstraction (an interface or an abstract class) register them also.

Related

How to resole a dependency using the consuming class metadata

The setup is below, I want IDependency used by Service to be created with attachedToClassName = nameof(Service) or indeed the actual class name, consuming IDependency.
I can't change constructors / interfaces, I'm looking for a solution working with .NET Core DI (no side libs).
public class OtherDependency: IOtherDependency
{
}
public class Dependency: IDependency
{
public Dependency(IOtherDependency otherDependency, string attachedToClassName) {...}
}
public class Service
{
//
public Service(IDependency dependency)
{
}
}
the better approach would be the same .net core uses for ILogger -> introducing the generic type. This means you should change your interfaces and you don't want to.
Let's dive in the difficult one.
We need to take a look at this method:
ObjectFactory ActivatorUtilitiess.CreateFactory(Type, Type[])
https://learn.microsoft.com/it-it/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createfactory?view=dotnet-plat-ext-3.1
This method returns an object factory for the type given as first parameter.
ObjectFactory is a delegate:
public delegate object ObjectFactory(IServiceProvider serviceProvider, object[] arguments);
https://learn.microsoft.com/it-it/dotnet/api/microsoft.extensions.dependencyinjection.objectfactory?view=dotnet-plat-ext-3.1
than we also need this overload of IServiceCollection.AddSingleton (or wathever lifetime)
public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> factory)
in your Startup.ConfigureServices you should the following:
var objFactory1 = ActivatorUtilities.CreateFactory(typeof(Dependency1), new Type[]{typeof(string)});
var objFactory2 = ActivatorUtilities.CreateFactory(typeof(Dependency2), new Type[]{typeof(string)});
//and so on for all your concrete dependencies
var serviceObjFactory1 = ActivatorUtilities.CreateFactory(typeof(Service1), new Type[] {typeof(IDependency)});
services.AddSingleton(typeof(Service1),sp => serviceObjFactory1(sp, new object[] {
objFactory1(sp, new object[]{"attached for Service1"})
});
with the object factory you instantiate a class that retrieves all the dependency from the service provider except the dependencies of the types you specified when you created the factory. Those dependencies instances must be given when you invoke the factory

Create Instance of a class from interface which it implements

Hi I am trying to build a generic UoWFactory which creates a UnitOfWork(there will be one default unitofwork and multiple custom implementaitons as well). So far I was able to create factory method which creates default UoW and returns it. I have modify the following method to return specified UoW depending on the parameter passed.
Current implementation
private BaseResult<IUnitOfWork> GetUnitOfWorkByCompiledModel<IUnitOfWork>(DbCompiledModel compiledModel)
{
return new BaseResult<IUnitOfWork>
{
Payload = new DbUnitOfWork(_context, _dbRepository, _mapper, _entityMapper)
};
}
I wish to have something like this
private BaseResult<TUoW> GetUnitOfWorkByCompiledModel<IUnitOfWork>(DbCompiledModel compiledModel) where TUoW :Class
{
return new BaseResult<TUoW>
{
//Create instance of type TUoW where TUoW can be IUnitOfWork, ICustomUnitOfWork etc
//DbUnitOfWork implements IUnitOfWork and CustomUnitOfWork implements ICustomUnitOfWork
//All the TUoW will have constructors with identical parmeters
};
}
Create an instance of class is straight forward
Activator.CreateInstance (Type type, object[] args);
But if I pass Interface type as a parameter how to create instance of DbUnitOfWork or CustomUnitOfWork.
eg:-
GetUnitOfWorkByCompiledModel<IUnitOfWork>(compiledModel);
GetUnitOfWorkByCompiledModel<ICustomUnitOfWork>(compiledModel);
Parameterless constructors
What you want is possible, except for one thing: you can't use non-default constructors with generic type arguments. You can't avoid that.
Part of the issue here is that you can't enforce specific constructor method signatures from an interface, so there is no way to guarantee that all implementation of IUnitOfWork are going to have the same constructor.
The simplest solution here is to step away from using constructors and instead use object initialization:
public interface IUnitOfWork
{
Foo Foo { get; set; }
}
private BaseResult<TUnitOfWork> GetUnitOfWorkByCompiledModel<TUnitOfWork>(DbCompiledModel compiledModel) where TUnitOfWork : IUnitOfWork, new()
{
return new BaseResult<TUnitOfWork>
{
Payload = new TUnitOfWork()
{
Foo = myFoo
};
};
}
I think this suits your expectations while being a minimal change.
Resolving interfaces
But if I pass Interface type as a parameter how to create instance of DbUnitOfWork or CustomUnitOfWork. eg
GetUnitOfWorkByCompiledModel<IUnitOfWork>(compiledModel);
GetUnitOfWorkByCompiledModel<ICustomUnitOfWork>(compiledModel);
If you intend to use interface types without concrete types, then the above answer is incomplete.
Regardless of the generic type issue, if you want to resolve an interface into a concrete type, you need to register which concrete type you want to use.
This is most commonly done via a Dependency Injection framework. These framework ask you to register all necessary types, e.g. a .NET Core example:
services.AddTransient<IUnitOfWork, MyUnitOfWork>();
services.AddTransient<ICustomUnitOfWork, MyCustomUnitOfWork>();
And the framework will then use this registration to automatically fill in constructor parameters for you:
public class Example
{
public Example(ICustomUnitOfWork uow)
{
}
}
The good practice approach here requires you to thread this dependency injection through your entire framework so you never need to call any constructor explicitly (and instead have the DI framework do it for you).
It is possible to use a service locator, which is essentially a DI framework that you call at-will. A small example of usage would be:
private BaseResult<TUnitOfWork> GetUnitOfWorkByCompiledModel<TUnitOfWork>(DbCompiledModel compiledModel) where TUnitOfWork : IUnitOfWork, new()
{
var uow = myServiceLocator.Get<TUnitOfWork>();
uow.Foo = myFoo;
return new BaseResult<TUnitOfWork>
{
Payload = uow;
};
}
This creates an instance of whichever concrete type was registered to the interface you're using as the generic parameter.
However, service locators are generally considered to be an anti-pattern, and I would strongly suggest that you avoid favor a cleaner IoC approach than this.
I can't elaborate fully on dependency injection in scope of a single StackOverflow answer. I suggest you look up dependency injection as it does exactly what you're expecting (getting a concrete type by referencing an interface)
This will be work if DbUnitOfWork Class has right name of values
What you want to change
Payload = new DbUnitOfWork(_context, _dbRepository, _mapper, _entityMapper);
Change as
Payload = new DbUnitOfWork() {
context = _context,
dbRepoitory = _dbRepository,
mapper = _mapper,
entityMapper = _entityMapper
};
hope this work.

Use Autofac for non-registered type initialization

I have a library that builds instances of types (all public and non-abstract) it discovers dynamically at runtime (using reflection).
To build those instances I want to use Autofac (though I'm willing to use other frameworks) so that the dependencies are automatically incorporated.
The problem is that Autofac is not creating the instance. If I use scope.Resolve() it throws an exception saying the type wasn't registered (which it can't be since it is discovered dynamically at runtime). If I try to use scope.ResolveOptional() it just returns null.
I've used it with types that have just a default public constructor and types that have dependencies and both fail.
EDIT: Added code. The types returned in the types array are all public types with a default parameterless constructor.
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(ISomeInterface).IsAssignableFrom(p)
&& !p.IsAbstract
&& p.IsPublic).ToArray();
var instance = (ISomeInterface)_dependencyInjectionScope.Resolve(type);
EDIT 2: Regarding some comments, yes I know that these types are not registered beforehand but that happens because the container is already fully built by the time this code is called. I'm looking if there is a way around it (after all I'm providing Autofac with a type that is both concrete and constructable)
Are you eventually looking for Registration Sources?
If so, please see the AnyConcreteTypeNotAlreadyRegisteredSource:
var builder = new ContainerBuilder();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
though I'm willing to use other frameworks
You can use the Unity container. It allows you to build objects of any class (not interfaces) without explicitly registering the classes with the container. Of course the classes have to be public, non-abstract, have a public constructor, and interface-based dependencies should be registered with the container.
Here is a sample code:
public interface IService
{
}
public class Service : IService
{
}
public class MyClass
{
private readonly IService m_Service;
public MyClass(IService service)
{
m_Service = service;
}
}
class Program
{
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<IService, Service>(); //We need to register interface-based dependency
var my_class = container.Resolve<MyClass>(); //We can resolve class-based types without registering them explicitly
}
}

Inject dependency as method parameter instead of constructor parameter

Can we inject dependency as method parameter instead of constructor parameter either using MEF or Autofac?
Thanks
I don't know about MEF, as I've never used it. You can do it with Unity and with Autofac
Unity
From the MSFT documentation.
Unity instantiates dependent objects defined in parameters of methods that carry the InjectionMethod attribute within the scope of the target object. Then it calls the attributed method of the target object before returning the object to the caller. You must apply the InjectionMethod attribute in the target class to initiate method call injection.
public class MyObject
{
public SomeOtherObject dependentObject;
[InjectionMethod]
public void Initialize(SomeOtherObject dep)
{
// assign the dependent object to a class-level variable
dependentObject = dep;
}
}
That will mark the class as having a dependency method that must get invoked when the class is instanced, and have its method parameter injected.
IUnityContainer uContainer = new UnityContainer();
MyObject myInstance = uContainer.Resolve<MyObject>();
// access the dependent object
myInstance.dependentObject.SomeProperty = "Some value";
Autofac
Autofac does it through lambdas or callbacks during the activation of a service. From the Autofac documentation
While constructor parameter injection is the preferred method of passing values to a component being constructed, you can also use property or method injection to provide values.
Property injection uses writeable properties rather than constructor parameters to perform injection. Method injection sets dependencies by calling a method.
// Register the type that you want to resolve with a resolution callback. Within the callback, invoke the method with a resolved dependency.
builder.Register(c => {
var result = new MyObjectType();
var dep = c.Resolve<TheDependency>();
result.SetTheDependency(dep);
return result;
});
An alternative is the registration callback.
builder
.Register<MyObjectType>()
.OnActivating(e => {
var dep = e.Context.Resolve<TheDependency>();
e.Instance.SetTheDependency(dep);
});
Both frameworks can only do the method injection at the time of resolution. However, you can't inject a dependency in to a method after the object has been instanced. In those scenarios, you should use a factory to fetch the dependency you have, having the factory resolve it through your DI container.
Factory
// Create the factory. The factory will have a static method that the DI system can register a lambda with, so that the factory can resolve through the DI container without being tightly coupled to it.
public class BarFactory
{
private static Func<IBarDependency> internalFactory;
public static void SetFactory(Func<IBarDependency> factory)
{
this.internalFactory = factory;
}
public IBarDependency CreateBar()
{
// Use the DI container lambda assigned in SetFactory to resolve the dependency.
return internalFactory();
}
}
public class DependencyInjectionBootstrap
{
IContainer container;
public void SetupDI()
{
var builder = new ContainerBuilder();
builder.RegisterType<BarDependency>().As<IBarDependency>();
container = builder.Build();
// Tell the factory to resolve all IBarDependencies through our IContainer.
BarFactory.SetFactory(() => container.Resolve<IBarDependency>());
}
}
public class FooViewModel
{
public void ExecuteSave()
{
var barFactory = new BarFactory();
IBarDependency bar = barFactory.CreateBar();
}
}

Why can't I bind System.IO.Abstractions with Ninject?

I am just learning to use dependency injection with Ninject, and am using System.IO.Abstractions to abstract the filesystem. I am trying to use Ninject to bind DirectoryInfoBase to DirectoryInfo as so:
IKernel ninject = new StandardKernel();
ninject.Bind<DirectoryInfoBase>().To<DirectoryInfo>();
But am getting the error
Error 1 The type 'System.IO.DirectoryInfo' cannot be used as type parameter 'TImplementation' in the generic type or method 'Ninject.Syntax.IBindingToSyntax.To()'. There is no implicit reference conversion from 'System.IO.DirectoryInfo' to 'System.IO.Abstractions.DirectoryInfoBase'. C:\Users\Trevor\Dropbox\Code\PhotoOrganiser\PhotoOrganiser\Program.cs 13 13 PhotoOrganiserApp
What am I missing here? I thought the goal of libraries such as this was to be able to perform these sorts of tasks?
System.IO.Abstractions is using the Adapter Pattern. It is a trick used for certain types that don't have any abstraction (abstract class or interface) in order to use them with DI. Since there is no way to add an abstraction to an existing type in .NET, a wrapper (adapter) is created which has an abstraction (in this case, an abstract class) in order to use to loosely couple the implementation.
The problem here is that you are not using the wrapper, you are using the implementation directly.
IKernel ninject = new StandardKernel();
ninject.Bind<DirectoryInfoBase>().To<DirectoryInfoWrapper>()
.WithConstructorArgument("instance", new DirectoryInfo(#"C:\Somewhere\"));
However, there is another gotcha here - DirectoryInfo requires a directory path as a constructor argument. So this means it typically makes more sense to use an Abstract Factory so it can be created at runtime when the directory path is known. In this case, it makes more sense to inject the factory into your service and then call the method to create the instance at runtime. The author of System.IO.Abstractions made the factory internal, but you can build one just the same.
[Serializable]
public class DirectoryInfoFactory : IDirectoryInfoFactory
{
public DirectoryInfoBase FromDirectoryName(string directoryName)
{
var realDirectoryInfo = new DirectoryInfo(directoryName);
return new DirectoryInfoWrapper(realDirectoryInfo);
}
}
public class SomeService : ISomeService
{
private readonly IDirectoryInfoFactory directoryInfoFactory;
public SomeService(IDirectoryInfoFactory directoryInfoFactory)
{
if (directoryInfoFactory == null)
throw new ArgumentNullException("directoryInfoFactory");
this.directoryInfoFactory = directoryInfoFactory;
}
public void DoSomething()
{
// The directory can be determined at runtime.
// It could, for example, be provided by another service.
string directory = #"C:\SomeWhere\";
// Create an instance of the DirectoryInfoWrapper concrete type.
DirectoryInfoBase directoryInfo = this.directoryInfoFactory.FromDirectoryName(directory);
// Do something with the directory (it has the exact same interface as
// System.IO.DirectoryInfo).
var files = directoryInfo.GetFiles();
}
}
And then configure the container to inject a factory that can create multiple runtime instances rather than a single instance.
IKernel ninject = new StandardKernel();
ninject.Bind<IDirectoryInfoFactory>().To<DirectoryInfoFactory>();
But there is another trick the author of System.IO.Abstractions used to take it a step further. He made an Aggregate Service that can be injected and provide many of the services that types in the System.IO namespace provide in a loosely-coupled way.
So, rather than making your own factory, you could instead inject the existing IFileSystem service in order to gain access to virtually any of the services the System.IO namespace provides.
public class SomeService : ISomeService
{
private readonly IFileSystem fileSystem;
public SomeService(IFileSystem fileSystem)
{
if (fileSystem == null)
throw new ArgumentNullException("fileSystem");
this.fileSystem = fileSystem;
}
public void DoSomething()
{
// The directory can be determined at runtime.
// It could, for example, be provided by another service.
string directory = #"C:\SomeWhere\";
// Create an instance of the DirectoryInfoWrapper concrete type.
DirectoryInfoBase directoryInfo = this.fileSystem.DirectoryInfo.FromDirectoryName(directory);
// Do something with the directory (it has the exact same interface as
// System.IO.DirectoryInfo).
var files = directoryInfo.GetFiles();
}
}
You would then configure the container just to inject IFileSystem to gain all of the functionality of System.IO.
IKernel ninject = new StandardKernel();
ninject.Bind<IFileSystem>().To<FileSystem>();
You can't use that particular binding because DirectoryInfo doesn't inherit from or implement DirectoryInfoBase.
You might have been misled by the fact you can do cast a DirectoryInfo to a DirectoryInfoBase using
DirectoryInfo dirInfo;
DirectoryInfoBase dirInfoBase = (DirectoryInfoBase)dirInfo;
but that is only possible because of an implicit cast operator in DirectoryInfoBase:
public static implicit operator DirectoryInfoBase(DirectoryInfo directoryInfo)
{
if (directoryInfo == null)
return null;
return new DirectoryInfoWrapper(directoryInfo);
}
I'm not familiar with System.IO.Abstractions but why don't you just inject the IFileSystem, like in the example with
ninject.Bind<IFileSystem>().To<FileSystem>();
If you have a IFileSystem you can do
fileSystem.DirectoryInfo.FromDirectoryName(directoryName)
to get a DirectoryInfoBase object.

Categories

Resources