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
Related
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.
I'm working on a .NET Core Project. I need to automatically registers a default for some raw generics. When there parameter count is the same everything works fine.
public void RegisterServiceDefaults(IServiceCollection services)
{
services.AddSingleton(typeof(IAdaptable<,>), typeof(DynamicAdapter<,>));
}
My IAdaptable<TEntity, TDTO> works to allow dynamic adaptation between entities, but in my concrete services by default we expect an interface so we can control how each property is adapted to, my IAdaptable<TEntity, TDTO> is really just a wrapper for convenience on this interface
IAdaptable<TEntity, TIDTO, TDTO>
where TDTO: TIDTO
{
}
IAdaptable<TEntity, TDTO> : IAdaptable<TEntity, TDTO, TDTO>
{
}
How can I generically register my adaptables so that if someone requests an IAdaptable<TEntity, TDTO, TDTO> it will by default return the IAdaptable<TEntity, TDTO>?
EDIT Provided for understanding the problem TL;DR
This is being used for a rest framework which provides two ways of registration, the end user can create an IAdaptable<TEntity, TIDTO, TDTO> a sample adapter might looks like so:
public UserAdapter : IAdaptable<User, IUserDTO, UserDTO>, IUserDTO
{
User _user;
public UserAdapter(User user)
{
this._user = user;
}
public int Id
{
get => this._user.Id;
set { /*Do nothing you cannot override the server Id*/}
}
//... The rest of the User Properties
}
When a the end user creates a service they can use an IAdaptable<TEntity, TIDTO, TDTO> or if they do not want to create a concrete one they can pass some options to the dynamic one which is only aware of the TEntity, and TDTO property, no reason to create an TIDTO when it's only used for adapting.
Now when the end user creates a service they can rely on either interface, the GenericBase service by default requests an IAdaptable like so:
public class RestService<TEntity, TIDTO, TDTO>
where TDTO: TIDTO
{
public RestService(DbContext context, IAdaptable<TEntity, TIDTO, TDTO> adapter, IValidator<TEntity> validator)
{
}
}
and for a simplified version:
public class RestService<TEntity, TDTO> : RestService<TEntity, TDTO, TDTO>
{
//Implementation...
}
Now generally speaking, if the end user wants a dynamic adapter they should be using the simplified RestService, but depending on their architecture they maybe implement interfaces on the DTOs or maybe they just used the more explicit base and decide to use the RestService<TEntity, TIDTO, TDTO>, In which case will leave them with a nasty runtime error. So to avoid having my support team handle the end user error, I would like to avoid the situation and have the IAdaptable<TEntity,TIDTO, TDTO> work with my dynamic adapter which is a IAdaptable<TEntity,TDTO>.
You can create your own scanning implementation using Reflection to register multiple types with a single line.
ServiceCollectionExtensions
Here we implement a simple Scan extension method that allows you to pick an an interface (whether generic or non-generic) and all implementations of that interface will be registered for all of the provided assemblies.
public static class ServiceCollectionExtensions
{
public static IServiceCollection Scan(
this IServiceCollection serviceCollection,
Assembly assembly,
Type serviceType,
ServiceLifetime lifetime)
{
return Scan(serviceCollection, new Assembly[] { assembly }, serviceType, lifetime);
}
public static IServiceCollection Scan(
this IServiceCollection serviceCollection,
IEnumerable<Assembly> assemblies,
Type interfaceType,
ServiceLifetime lifetime)
{
foreach (var type in assemblies.SelectMany(x =>
x.GetTypes().Where(t => t.IsClass && !t.IsAbstract)))
{
foreach (var i in type.GetInterfaces())
{
// Check for generic
if (i.IsGenericType && i.GetGenericTypeDefinition() == interfaceType)
{
var genericInterfaceType = interfaceType.MakeGenericType(i.GetGenericArguments());
serviceCollection.Add(new ServiceDescriptor(genericInterfaceType, type, lifetime));
}
// Check for non-generic
else if (!i.IsGenericType && i == interfaceType)
{
serviceCollection.Add(new ServiceDescriptor(interfaceType, type, lifetime));
}
}
}
return serviceCollection;
}
// TODO: Add overloads ScanTransient, ScanSingleton, etc that call the
// above with the corresponding lifetime argument
}
Usage
To register all of the types that close the generic IAdaptable<,,> type and register them as singleton, you would then simply need to use:
services.Scan(
assembly: typeof(User).Assembly,
interfaceType: typeof(IAdaptable<,,>),
lifetime: ServiceLifetime.Singleton);
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
}
}
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();
}
}
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.