Generic factories impossible when requiring dependency injection? - c#

I am trying to make some generic factories for my service factories and dao factories and am running into some limitations.
Typically my service and dao factories look like this:
public static class PersonServiceFactory
{
private static PersonService personService;
public static PersonService GetInstance()
{
if (personService == null)
{
PersonDao personDao = PersonDaoFactory.GetInstance();
personService = new PersonService(personDao);
}
return personService;
}
}
public static class PersonDaoFactory
{
private static PersonDao personDao;
internal static PersonDao GetInstance()
{
if (personDao == null)
{
personDao = new PersonDao();
}
return personDao;
}
}
Then I tried doing a generic factories:
public abstract class EntityDaoFactory<daoClass>
where daoClass : class, new()
{
private static daoClass factorySupportClass;
internal static daoClass GetInstance()
{
if (factorySupportClass == null)
{
factorySupportClass = new daoClass();
}
return factorySupportClass;
}
}
public abstract class EntityServiceFactory<serviceClass, daoClass>
where serviceClass : class, new()
where daoClass : class
{
private static serviceClass factorySupportClass;
internal static serviceClass GetInstance()
{
if (factorySupportClass == null)
{
//daoClass daoSupportClass = *how to get daoSupportClassfactory.GetInstance(); here?*
factorySupportClass = new serviceClass(daoSupportClass);
}
return factorySupportClass;
}
}
So they could used like this:
public static class PersonDaoFactory : Entities.EntityDaoFactory<PersonDao>
{
}
public static class PersonServiceFactory : Entities.EntityServiceFactory<PersonService, PersonDaoFactory>
{
}
Here are the problems I am running into:
Can't use static class as type constraint for generics, which I was trying to use for the EntityServiceFactory, because without it I don't know how to inject the appropriate dao.
Can't have the factories derive from the Generic factories because I get an error like:
Static class 'Persons.PersonDaoFactory' cannot
derive from type
'Entities.EntityDaoFactory'.
Static classes must derive from object.
Tried making them all non-static classes with private constructors to get around that but then I get:
'Persons.PersonService' must be a non-abstract type with a public
parameterless constructor in order to use it as parameter
'serviceClass' in the generic type or method
'Entities.EntityServiceFactory
I was able to read why number 3 occurs on here, but that still doesn't solve my problems. I got the DaoFactory working, but it only works if the specific DaoClass doesn't need any dependency injection, otherwise error 3 pops up again.
Is there anyway to get these generic factories working using a different approach while still being able to use DI?
EDIT ----
I was able to get this sort of working, but it has some oddities. First I created a IEntityFactory interface:
public interface IEntityFactory<T>
where T : class
{
T GetInstance();
}
Then changed the EntityDaoFactory to:
public abstract class EntityDaoFactory<daoClass> : IEntityFactory<daoClass>
where daoClass : class, new()
{
private static daoClass factorySupportClass;
public daoClass GetInstance()
{
if (factorySupportClass == null)
{
factorySupportClass = new daoClass();
}
return factorySupportClass;
}
}
So I could pass in the appropriate type parameters and change the EntityServiceFactory to:
public abstract class EntityServiceFactory<serviceClass, daoClass, daoFactoryClass>
where serviceClass : class, new()
where daoClass : class, new()
where daoFactoryClass : IEntityFactory<daoClass>, new()
{
private static serviceClass factorySupportClass;
public static serviceClass GetInstance()
{
if (factorySupportClass == null)
{
daoFactoryClass daoSupportFactory = new daoFactoryClass();
daoClass daoSupportClass = daoSupportFactory.GetInstance();
factorySupportClass = new serviceClass();
}
return factorySupportClass;
}
}
So for a specific implementation such as with the Person object the calls look like:
public class PersonDaoFactory : Entities.EntityDaoFactory<PersonDao>
{
}
public class PersonServiceFactory : Entities.EntityServiceFactory<PersonService, PersonDao, PersonDaoFactory>
{
}
So it's working now, but the oddities are:
You can instantiate a factory, which was required (as far as I know the only way to do it?) for the EntityServiceFactory, but for someone using my API there would be no reason for them to do it but they still could.
Services and DAOs which have dependency requirements can now be instantiated with no parameters, which would break the instantiated class methods (but I had to do it to be able to use it as a type parameter). They shouldn't even ever by instantiating these objects anyway but they can now and do so incorrectly.
Also a final problem I just thought of is this solution doesn't really handle a variable amount of dependencies well. Still wonder if there is a better approach for this?
Conclusion: I think in the end even though it works, I gave up a lot of order to have that generic factory, which isn't that flexible and not giving me much, so I probably wouldn't use it in this case due to the limitations.

First of all, you are NOT using dependency injection. Depencency injection has nothing to do with providing type parameters to a generic class / method.
The errors occur because you are violating C#'s rules. You have to change your code to conform with them. So, make your classes non-static and do not use private constructors. You can replace a static class with a singleton instance and use protected constructors to avoid uncontroller instantiation.

I know that this question is really old, but I stumbled across it, so I figure I would give an answer.
The following compiles and does what you are looking to do:
public abstract class Entity<serviceFactory, serviceClass, daoFactory, daoClass>
where daoFactory : Entity<serviceFactory, serviceClass, daoFactory, daoClass>.DaoFactory, new()
where daoClass : class, new()
where serviceFactory : Entity<serviceFactory, serviceClass, daoFactory, daoClass>.ServiceFactory, new()
where serviceClass : class, new()
{
public abstract class DaoFactory
{
private static daoClass factorySupportClass;
internal static daoClass GetInstance()
{
if (factorySupportClass == null)
{
factorySupportClass = new daoFactory().createDao();
}
return factorySupportClass;
}
protected abstract daoClass createDao();
}
public abstract class ServiceFactory
{
private static serviceClass factorySupportClass;
internal static serviceClass GetInstance()
{
if (factorySupportClass == null)
{
daoClass daoSupportClass = DaoFactory.GetInstance();
factorySupportClass = new serviceFactory().createService(daoSupportClass);
}
return factorySupportClass;
}
protected abstract serviceClass createService(daoClass dao);
}
}
Now unless you are planning on using these types from within a composition root, I strongly recommend against doing the above solution since some of your dependencies are hidden and worse, are fixed to a limited set of parameters. Instead try something like this for a more DI/composition root friendly solution.

Related

Generic base class constructor

Using this generic base class:
public abstract class Logic<U> where U : class
{
protected U m_provider;
public Logic(U provider)
{
m_provider = provider;
}
}
I'm trying to create a base test class for unit test:
public class LogicBaseTest<T, U> where T : Logic <U>, new() where U: class
{
protected T m_logic;
protected U m_provider;
[OneTimeSetUp]
public virtual void OneTimeSetup()
{
m_provider = (U)Substitute.For<IInterface>();
m_logic = new T(m_provider);
}
}
It complains on the constructor, it requests for the new() constrain but when I add it then it complains that the constructor cannot take parameters.
I could add a method to populate the provider but I'm wondering whether it could be done in the constructor.
So you have two problems here:
LogicBaseTest needs to know how to instantiate a Logic<U>.
Logic<U> requires a U in the constructor.
My proposed solution to it is to pass a factory delegate into the base test class and remove the new() requirement. Then your setup can construct the Logic class using the factory:
public class LogicBaseTest<T, U>
where T : Logic<U>
where U: class
{
protected readonly Func<U, T> _factory;
public LogicBaseTest(Func<U, T> factory)
{
_factory = factory;
}
[OneTimeSetUp]
public virtual void OneTimeSetup()
{
m_provider = (U)Substitute.For<IInterface>();
m_logic = _factory(m_provider);
}
}
In the derived test class you just have to tell the base class how to new up a Logic<U>:
public class DerivedTest : LogicBaseTest<Logic<MyUType>, MyUType>
{
public DerivedTest()
: this(u => new Logic<MyUType>(u))
{
}
}
Let's break down your generic constraint into plain English
where T : Logic<U>, new()
This means
The type of T needs to inherit from Logic, the generic type parameter must be U and have a public, parameterless, constructor
But the problem is that Logic by itself already breaks that constraint. Now, how do we fix this? There are multiple ways
Use a "factory function" to instantiate your m_logic alongside removing the new constraint (see DiplomacyNotWar's answer)
Remove the new() constraint and use something like Activator.CreateInstance instead to instantiate your Logic class
Add a parameterless constructor to Logic and configure your m_provider some other way
Move instantiation of m_logic into the unit test itself (maybe add a helper method if you need to create the same Logic for a ton of unit tests)
Research if your unit testing framework supports some form of Dependency Injection and inject everything you need
You cannot add a generic type constraint such as where T : new(U).
Instead, you can use a Factory.
public interface IFactory<out TObject, in TProvider>
{
public TObject Create(TProvider provider);
}
then use it in your base test
public class LogicBaseTest<T, U> where T : Logic <U> where U: class // remove new()
{
// fields
private readonly IFactory<T, U> _factory;
public LogicBaseTest(IFactory<T, U> factory)
{
_factory = factory;
}
[OneTimeSetUp]
public virtual void OneTimeSetup()
{
m_provider = (U)Substitute.For<IInterface>();
m_logic = _factory.Create(m_provider);
}
}
Example
public class Logic1Provider
{
}
public class Logic1Factory : IFactory<Logic1, Logic1Provider>
{
public Logic1 Create(Logic1Provider provider)
{
return new Logic1(provider);
}
}
public class Logic1 : Logic<Logic1Provider>
{
public Logic1(Logic1Provider provider) : base(provider)
{
}
public void DoDomeLogic()
{
// do stuff
}
}
var factory = new Logic1Factory();
var baseTest = new LogicBaseTest<Logic1, Logic1Provider>(factory);

C#: Protected Variables inside of a Generic Class can be accessed by a different subclass of that Generic Class. Can I prevent this?

Say I have a generic class Foo, that has a variable that is protected
public class Foo<T>
{
protected bool knowsFu;
}
I also have 2 sub-classes: Bar and Pipe
public class Bar : Foo<Bar> {}
public class Pipe : Foo<Pipe> {}
It is actually possible for me to access the knowsFu in Pipe FROM Bar, e.g.:
public class Bar : Foo<Bar>
{
void UpdateFuInOtherClass(Pipe p)
{
p.knowsFu = false;
}
}
Is this intended behaviour? (If so, what would be the usecase?)
Is there a way for me to prevent other Foo-Subclasses from modifying/reaching the protected variable inside of my current subclass?
More specifically: I'm using a generic class to implement the Singleton-Pattern:
https://en.wikipedia.org/wiki/Singleton_pattern
However, I'm currently able to access any singleton's protected instance-variable, as long as I am inside of another Singleton. Is there a way to prevent this?
EDIT: It might be relevant to note that the protected variable (knowsFu) is actually STATIC as well.
EDIT2: Ok, maybe the example was abit too generic.. here's how I'm actually currently implementing it:
why use Singleton? A:The platform I'm working on is Unity3D, in which the pattern is used frequently
I have a generically typed abstract class SingletonBehaviour
public abstract class SingletonBehaviour<T> where T : MonoBehaviour
{
public static T Instance { get { return instance; } }
protected static T instance { get; private set; } }
// Loading is done through Unitys Awake-Method
}
One of the Singleton-Objects that I'm using is the APIManager
public class APIManager : SingletonBehaviour<APIManager>
{
// Methods like SendHTTPPost(), HTTPGet(), etc.
}
However, since most of my projects need some better API-implementation than that, what I'm currently doing is:
public class ProjectAAPIManager : APIManager
{
// Overriding Instance so my return value is not APIManager but instead ProjectAAPIManager
public static new ProjectAAPIMamager Instance { get { return (ProjectAAPIManager)instance; } }
}
This ^ is the reason my (inner) instance-variable is protected, and not private.
However, because of this, any other SingletonBehaviour in my project can now access the (inner) instance-variable on my ProjectAAPIManager
public class GameController : SingletonBehaviour<GameController>
{
private void AMethod()
{
// Accessing inner variable instead of public one
ProjectAAPIManager.instance.DoSomething();
}
}
As it's only the getter, this currently does not really matter. But what if I'd need access to the setter in my subclass as well?
Also: would it be worth it to generically type my APIManager as well?
Your question is nothing short of bewildering. How can you make a protected member not be accesible from a derived class? Well, a good start is not making it protected.
protected is by definition exactly what you don't want, so don't use it! Use private instead.
If what you are asking is how to make it a readonly member when accessed from derived types, you have two options:
Declare it as readonly in the base class if possible.
Use a protected property instead with a private setter.
Many novice coders seems to think protected members aren't part of the public surface of the type but they really are, as long as the class can be extended. As such, the rules of public members apply: never expose public fields unless they are readonly or constants, use properties instead.
You should not have classes that implement your generic singleton class.
Otherwise, by default, your protected fields will be accessible by the subclasses (it's what "protected" keyword does)
Instead, you should do something like this:
class Program
{
static void Main(string[] args)
{
var barInstance = Foo<Bar>.GetInstance();
}
}
public class Foo<T> where T : new()
{
protected bool knowsFu;
private static T _instance;
public static T GetInstance()
{
if (_instance == null)
_instance = new T();
return _instance;
}
}
public class Bar
{
public Bar()
{
}
}
Edit 1:
To use a singleton, you should not make another class implement the singleton behavior (This is not how the singleton pattern works).
To use the same classes as your second example, you should do something like this.
public class SingletonBehaviour<T> where T : new()
{
public static T Instance
{
get
{
if(instance == null)
instance = new T()
return instance;
}
}
private static T instance { get; set; }
}
public class APIManager // This class should not inherit from the SingletonBehavior class
{
// Methods like SendHTTPPost(), HTTPGet(), etc.
}
public class ProjectAAPIManager : APIManager
{
public ProjectAAPIManager GetInstance() => SingletonBehavior<ProjectAAPIManager>.Instance();
}

How to apply functions from one interface to another interface while using generics on a base class?

I have two interfaces from a third party that have the same function. Since this is a third party's interface, I do not have the ability to attach a parent interface.
public interface IInterface1 {
int Open(string stringName);
}
public interface IInterface2 {
int Open(string stringName);
}
I am wanting to pass them into a base class
public class MyClass : BassClass<IInterfaceWithOpenFunction>
So that I can execute the same exact function on both classes the same way.
public class BassClass<T> Where T : IInterfaceWithOpenFunction, new()
{
private T item;
public BaseClass(string stringName)
{
item = new T();
item.open(stringName);
I'm not wanting to make item dynamic as I'm wanting to keep the intellisense, how do I achieve this?
Somehow IInterfaceWithOpenFunction needs to consume the function open of the other interfaces while allowing me to Pass in the desired Interface to implement.
What you can do in order to achieve this is create your own "parent" interface and derived classes each suitable for those different third party classes. Essentially you have different wrappers for the different non-related interfaces:
public interface IInterfaces
{
int Open(string stringName);
}
public class DerivedForInterface1 : IInterfaces
{
private IInterface1 _instance;
public DerivedForInterface1(IInterface1 instance)
{
_instance = instance;
}
public int Open(string stringName) => _instance.Open(stringName);
}
public class DerivedForInterface2 : IInterfaces
{
private IInterface2 _instance;
public DerivedForInterface2(IInterface2 instance)
{
_instance = instance;
}
public int Open(string stringName) => _instance.Open(stringName);
}
And then your base class:
public class BassClass<T> Where T : IInterface
In the implementation described above the specific instances of the third party interfaces are given as dependencies to your wrappers. By doing so no implementation on IInterfaces has a default constructor and thus you need to remove the new() generic constraint. There are other ways to implement it such as passing dependencies though properties instead of constructors. The different ways have their pros and cons and one can check the differences.
As for this part of your code:
item = new T();
item.open(stringName);
I think that maybe instead of initializing the type, as you are doing, you'd rather have your class hold a reference to the initialized types. Could be that the wrapper classes that I showed can replace the BaseClass you currently have.
If you insist on intellisense and a single manager to rule them all, then something like this can do:
public class Provider1Wrapper : IInterfaceWithOpenFunction
{
private Provider1 _provider; // Instance\Inject via CTOR
public int Open(string stringName)
{
return _provider.Open(stringName);
}
}
public class Provider2Wrapper : IInterfaceWithOpenFunction
{
private Provider2 _provider; // Instance\Inject via CTOR
public int Open(string stringName)
{
return _provider.Open(stringName);
}
}
public static class ProviderManager<T> where T : IInterfaceWithOpenFunction, new()
{
public static int Open(string stringName)
{
T providerWrapper = new T();
return providerWrapper.Open(stringName);
}
}
void Main()
{
var result = ProviderManager<Provider2Wrapper>.Open(stringName);
}

Extending functionality through interfaces

I have implemented an interface IService that inherits functionality from a series of other interfaces and serves as a common ground for many different services.
Each of these services is being described by an interface, for example:
public interface IServiceOne : IService
{
//...
}
public class ServiceOne : IServiceOne
{
//...
}
Everything up to that point works as expected:
IServiceOne serviceOne = new ServiceOne();
IServiceTwo serviceTwo = new ServiceTwo();
What I have to do now is to add a big list of constants (public variables) to each of these services which will however be different as per service type (for example, IServiceOne will have different constants than IServiceTwo, there will be constants in IServiceOne that will not exist in IServiceTwo, etc).
What I'm trying to achieve is something like that:
IServiceOne serviceOne = new ServiceOne();
var someConstantValue = serviceOne.Const.SomeConstant;
Just because the variables will differ as of service type I decided to implement an extra interface for each of them:
public interface IServiceOneConstants
{
//...
}
and then broaden my IService definition:
public interface IServiceOne : IService, IServiceOneConstants
{
//...
}
public class ServiceOne : IServiceOne
{
//...
}
The problem I have now is that I don't know how to implement the concrete class for IServiceOneConstants. Obviously by the time one of its variables (we called them constants here) will be called it has to be instantiated, so initially I though of a static class but then you cannot expose a static class's functionality through an interface. I then tried to do it with a singleton and expose its instance via a public non-static wrapper:
public class Singleton : IServiceOneConstants
{
private static Singleton _instance;
private Singleton()
{
SomeConstant = "Some value";
}
public static Singleton Instance
{
get
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
public String SomeConstant { get; set; }
public Singleton Const
{
get
{
return Instance;
}
}
}
I then adjusted the IServiceOneConstants like that:
public interface IServiceOneConstants
{
Singleton Const { get; }
}
but when I call this:
IServiceOne serviceOne = new ServiceOne();
var someConstantValue = serviceOne.Const.SomeConstant;
I get a null reference exception, as .Const is null.
What am I missing here?
You really helped yourself to get confused as possible, by naming different stuff same name ;)
So, first...
what you're trying to do is to access singleton instance through instance property:
public Singleton Const
{
get
{
return Instance;
}
}
then you are using it like:
serviceOne.Const
but that variable was never assigned. In order to assign it, you should make an instance of Singleton class, assign it to serviceOne.Const property and then you might use it.
What you need is probably something like this:
public class ServiceOne : IServiceOne
{
public Singleton Const
{
get
{
return Singleton.Instance;
}
}
}
You need to check to see if the singleton has been instantiated in ServiceOne.Const.SomeConstants` getter. If it's not, you need to instantiate it. Then return the value of the constant.

An inherited singleton class from a base class that takes parameters in its constructor?

public class BaseFoo
{
private string param;
public BaseFoo(string param)
{
this.param = param;
}
}
public sealed class SingletonFoo : BaseFoo
{
static readonly SingletonFoo instance = new SingletonFoo();
static SingletonFoo()
{
}
public static SingletonFoo Instance
{
get
{
return instance;
}
}
}
Is this kind of inheritance possible, where the base class requires a constructor with parameters? (The above code won't obviously compile because no parameter is passed to the base class.)
If yes, how is it accomplished?
You need to make an instance constructor, and then refer to it:
public sealed class SingletonFoo : BaseFoo
{
static readonly SingletonFoo instance = new SingletonFoo("Some Value");
static SingletonFoo()
{
}
private SingletonFoo(string value) : base(value)
{
}
// ...
This will let you declare the parameter in the inline constructor, and call it down the chain.
You use the 'base' keyword:
public SingletonFoo (string param) : base(param)
{
}
I'm pretty sure a 'singleton' deriving from a non-singleton base class completely invalidates the entire concept of the pattern, which is often used inappropriately to start with.
Static constructors do not take parameters, so the only way to pass them to the base class would be via constructor-chaining but I'm pretty sure you can't invoke an instance constructor from a static constructor...
What exactly are you trying to do here?

Categories