In my application I have the following class to get instances of an interface:
public static class ServiceProvider
{
private static readonly Dictionary<Type, dynamic> _serviceStorage;
private static readonly object _serviceLock;
static ServiceProvider()
{
_serviceLock = new object();
_serviceStorage = new Dictionary<Type, dynamic>();
}
public static T GetService<T>()
{
Type serviceType = typeof (T);
lock (_serviceLock)
{
if (!_serviceStorage.ContainsKey(serviceType))
{
_serviceStorage.Add(serviceType, (T) CreateService(serviceType));
}
}
return _serviceStorage[serviceType];
}
private static dynamic CreateService(Type serviceType)
{
Type implementationType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.FirstOrDefault(type => serviceType.IsAssignableFrom(type) && type.IsClass);
if (implementationType == null)
throw new NullReferenceException();
return Activator.CreateInstance(implementationType);
}
}
The implementation-class must implement the provided interface and have a parameterless constructor.
For example I have the interface IEventRegistrationService
which looks something like:
public interface IEventRegistrationService
{
void Register(string name, Action<object> callback);
}
and the implementation-class looks like:
internal class EventRegistrationService : IEventRegistrationService
{
public void Register(string name, Action<object> callback)
{
// Register the action with this name...
}
}
And the usage of my service looks like:
IEventRegistrationService service = ServiceProvider.GetService<IEventRegistrationService>();
Now I have an instance of my interface. Everything just works fine until here.
Now I want to make the IEventRegistrationService-interface generic to have the correct type in the callback-action. The "new" interface should look like:
public interface IEventRegistrationService<T>
{
void Register(string name, Action<T> callback);
}
And the implementation-class now looks like:
internal class EventRegistrationService<T> : IEventRegistrationService<T>
{
public void Register(string name, Action<T> callback)
{
// Register the action with this name...
}
}
And the usage should be like:
IEventRegistrationService<string> service = ServiceProvider.GetService<IEventRegistrationService<string>>();
But with this generic I get an exception in ServiceProvider
-class in the CreateService method.
The statement:
Type implementationType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.FirstOrDefault(type => serviceType.IsAssignableFrom(type) && type.IsClass);
returns null.
I guess this is because of the .IsAssignableFrom(type)
but I don't know how to solve this problem.
How can I check if a class implements a generic interface?
Edit:
I don't know what interface-type is expected.