Generic factory - expect certain constructor - c#

I want to provide a factory for a certain type of class restricted by a generic constraint, however I need to make sure that the product to create has a certain constructor in order to make my factory work.
public interface IFactory<TProduct>
where TProduct: class, IMyRestriction
{
TProduct Create();
}
Class which implements IMyRestriction:
public class MyRestriction : IMyRestriction {
public MyRestriction(IArgumentType1 arg1, IArgumentType2 arg2) {
...
}
}
which would make this work...
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct: class, IMyRestriction
{
public TProduct Create() {
// args provided by factory constructor
Activator.CreateInstance(typeof(TProduct), arg1, arg2);
}
}
... however not for a class like this:
public class MyDerivedRestriction : MyRestriction {
public MyDerivedRestriction()
: base(null, null)
{
}
}
The only way I'm able to restrict on a certain constructor using generics is with the new() constraint, but that doesn't make sense in this case.

You've essentially answered your own question -as you know the only type of constraint controlling the constructer is a parameterless one.
The only option left then is to use some sort of Initialization method in place of a constructor, and the logic you would usually do in the constructor do in the Init method
interface IMyRestriction
{
// use whichever arguments you wanted for construction
void Init(string myParam1, string myParam2)
}
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct: class, IMyRestriction, new()
{
public TProduct Create() {
TProduct p = new TProduct();
p.Init(arg1,arg2);
return p;
}
}

If you need to create different classes with different constructor signatures, you are probably looking for an Abstract Factory pattern, where each entity class has its own implementation of the Factory interface:
#region Restriction Types
public class MyRestriction : IMyRestriction {
public MyRestriction(IArgumentType1 arg1, IArgumentType2 arg2) {
...
}
}
public class MyDerivedRestriction : MyRestriction {
public MyDerivedRestriction()
: base(null, null)
{
}
}
#endregion
#region Factory interface
public interface IFactory<TProduct>
where TProduct: class, IMyRestriction
{
TProduct Create();
}
#endregion
#region Factory implementations for each entity
public class MyRestrictionFactory : IFactory<MyRestriction>
{
public MyRestriction Create()
{
// args provided by factory constructor
return new MyRestriction(arg1, arg2);
}
}
public class MyDerivedRestrictionFactory : IFactory<MyDerivedRestriction>
{
public MyDerivedRestriction Create()
{
return new MyDerivedRestriction();
}
}
#endregion
This may seem like creating more code, but each factory class can be tiny, plus it provides more type-safety and is more flexible, as the factory can deal with the idiosyncrasies of its entity.
As an extension of this pattern, people often add interfaces for each factory, to make it nicer to register in an IOC container and provide more abstraction, but you may not need this in your case. For example:
// this gets resolved in DI, so the IFactory<T> part is abstracted away
public interface IMyRestrictionFactory
{
MyRestriction Create();
}
public class MyRestrictionFactory : IFactory<MyRestriction>, IMyRestrictionFactory
{
public MyRestriction Create()
{
// args provided by factory constructor
return new MyRestriction(arg1, arg2);
}
}

In C# you can't put generic constraints, which define desired signature of constructor, except new() (parameterless constructor).
The best you can do here is either rely on run-time exceptions, or re-write initialization logic to use properties of IMyRestriction instead of constructor arguments:
interface IMyRestriction
{
IArgumentType1 Property1 { get; set; }
IArgumentType2 Property2 { get; set; }
}
public class MyFactory<TProduct> : IFactory<TProduct>
where TProduct : class, IMyRestriction, new()
{
public TProduct Create()
{
var product = new TProduct();
product.Property1 = arg1;
product.Property2 = arg2;
return product;
}
}

Related

How to override generic method with derived type in c#

I have the following classes:
public interface IService
{
void ApplyChanges<T>(T parameters) where T : ParamBase;
}
public class ServiceBase : IService
{
public virtual void ApplyChanges<T>(T parameters) where T : ParamBase
{ }
}
public abstract class Service : ServiceBase
{
public override void ApplyChanges<T>(T parameters) where T : ParamBase
{
Console.WriteLine(parameters.Param2);
//Apply changes logic here...
}
}
public abstract class ParamBase
{
public string Param1 { get; set; }
}
public class ParamA : ParamBase
{
public string Param2 { get; set; }
}
Here my test main class:
void Main()
{
var service = new Service();
var paramA = new ParamA();
paramA.Param2 = "Test2";
service.ApplyChanges<ParamA>(paramA);
}
What is wrong with that implementation? How can I access parameters.Param2from the overriden ApplyChanges method in my Service class?
The general idea is that I have a ServiceBase and I want to be able for its derived classes to pass different parameter types to the ApplyChanges method.
I'm making a leap here, but it sounds like you intend to have multiple "services", each with an associated parameter type.
Putting a type parameter on the method, as you have done in the example, forces all implementations of that method to be polymorphic. (The technical term for this is higher-rank quantification.)
Instead, you should associate the type parameter with the service itself. This allows a given implementation of the contract to declare which parameter type it's associated with. While you're at it, I wouldn't bother with the base classes or the type bounds.
interface IService<in T>
{
void ApplyChanges(T param);
}
class Param1
{
public int X { get; set; }
}
class Service1 : IService<Param1>
{
public void ApplyChanges(Param1 param)
{
param.X = 123;
}
}
class Param2
{
public int Y { get; set; }
}
class Service2 : IService<Param2>
{
public void ApplyChanges(Param2 param)
{
param.Y = 456;
}
}
You shouldnt impose stronger constraints for method overrides. An overridden method should expand the possible input parameters and reduce the possible outcomes. Otherwise it breaks Liskov Substitution Principle. C# does not allow you to do that.
That said, if you really want it, you could. You won't get compiler warnings in the calling code though. Use that solution if you cannot change the base class.
public class Service<TParam> : Service where TParam : ParamA
{
public override void ApplyChanges<T>(T parameters)
{
Console.WriteLine((parameters as TParam).Param2);
}
}
A better solution would be to add a type parameter to ServiceBase and IService.
public interface IService<TParam>
where TParam : ParamBase
{
void ApplyChanges(TParam parameters);
}
public abstract class ServiceBase<TParam> : IService<TParam>
where TParam : ParamBase
{
public virtual void ApplyChanges(TParam parameters)
{ }
}
public class Service : ServiceBase<ParamA>
{
public override void ApplyChanges(ParamA parameters)
{
Console.WriteLine(parameters.Param2);
}
}
Really, instead of replacing the interface's generic type, it is cleaner to use a "Type Guard". I say cleaner because the interface's method signature stays consistent, and really, what's more important than how your interface is used? (Obviously puppies are more important)
Within the method itself, you can make sure that the type is the one desired as such...
public void Method(ParentRequest req){
if(req is ChildRequest request){
//Do logic here
} else {
throw new Exception($"request is of type {req.GetType().Name} and must be of type ParentRequest");
}
}

How to specify in C# generics such T that is constructible from string? (generic type constraint)

I want to specify required default constructrion options for my T:
public interface IParameter<T> /* where T : T(string) */ {
T Value { get; set; }
}
so I would be able to construct it from given string if passible like this:
Value = "bla";
or at least like this:
Value = new T("bla");
So how to specify in C# generics such T that is constructible from string?
Unfortunately, that constraint is not legal. Only the parameterless constructor constraint is allowed:
where T : new()
Unfortunately, C# does not offer arbitrary constructor signature restrictions for generic parameters. Only a restricted number of constraints are supported, the closest one of which is the new constraint. However, it serves only for enforcing a parameterless constructor.
You can, however, work around this drawback by working with a factory object that takes a string and returns a T. First, define an interface for such factory objects:
public interface IFactory<T>
{
T Create(string str);
}
Subsequently, you can use that factory type in your interface:
public interface IParameter<TFactory, T>
where TFactory : IFactory<T>
{
T Value { get; set; }
}
If you want to be able to instantiate the factories at will, you can require them to have a parameterless constructor:
public interface IParameter<TFactory, T>
where TFactory : new(), IFactory<T>
{
T Value { get; set; }
}
Then, you could use a generic method to instantiate a T based on a string, e.g. as an extension method for your interface:
public static class ParameterUtilities
{
public static void AssignValue<TFactory, T>(this IParameter<TFactory, T> prm, string str)
where TFactory : new(), IFactory<T>
{
var factory = new TFactory();
prm.Value = factory.Create(str);
}
}
As an example of how to use this, let's assume the variable myPrm is an instance of that implements your IParameter interface with appropriate type arguments. You can then invoke something like this:
myPrm.AssignValue("Hello, World!");
You can't, because in generic type constraints you can't say that the type must have a specific constructor (only that it must have a parameterless constructor) nor say that it must have specific methods/operators.
BUT
public interface IFromString<T>
{
void DeserializeFromString(string str);
}
public class MyType : IFromString<MyType>
{
public int Value;
public void DeserializeFromString(string str)
{
Value = int.Parse(str);
}
}
public interface IParameter<T> where T : IFromString<T>, new()
{
T Value { get; set; }
}
public class Parameter<T> : IParameter<T> where T : IFromString<T>, new()
{
T Value { get; set; }
public void Load(string str)
{
Value = new T();
Value.DeserializeFromString(str);
}
}
A classical example... an interface that says that a type can be deserialized from (something) (xml very often :-) )
Use:
Parameter<MyType> parameter = new Parameter<MyType>();
parameter.Load(someStringLoadedFromSomewhere);
You can't specify a constructor in an interface. Depending on your requirements you could use an abstract class:
Pseudo code as not at machine with VS:
public abstract class BaseParameter<T>
{
public abstract void BaseParameter(string something);
T Value { get; set; }
}

Derived class instantiation in abstract base class in C#

My aim is to write an abstract base class which contains a method for deriving “child instances”. In this method already some computation is done which is common in all deriving classes.
The difficulty is that the base class is not able to create the child class on its own. So I introduced a type parameter T in my base class and a protected abstract method which shall return an instance of T.
public abstract class Base<T> where T : Base<T>
{
public T GetChild()
{
string param = ComplexComputation();
return NewInstanceFrom(param);
}
protected abstract T NewInstanceFrom(string param);
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public Derivative() { }
protected sealed override Derivative NewInstanceFrom(string param)
{
return new Derivative(param);
}
private Derivative(string param)
{
// some configuration
}
}
The disadvantage of this approach is that I cannot ensure that NewInstanceFrom is only invoked by the base class. It could also be invoked by classes inheriting from Derivative. That’s what I want to avoid.
So I could encapsulate the functionality in a private class or delegate:
public abstract class Base<T> where T : Base<T>
{
public T GetChild()
{
string param = ComplexComputation();
return subElementDerivator(param);
}
protected Base<T>(Func<string, T> subElementDerivator)
{
this.subElementDerivator = subElementDerivator;
}
private Func<string, T> subElementDerivator;
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public Derivative()
: base(deriveSubElement)
{
}
private Derivative(string param)
: base(deriveSubElement)
{
// some configuration
}
private static Derivative deriveSubElement(string param)
{
return new Derivative(param);
}
}
But this introduces a new object.
Is there a simpler way to prevent access to a functionality (which the base class shall have access to) from heirs of Derivative?
You can use explicit interface implementation to hide your factory method. Any client can still call the Create method after casting but at least intellisense won't help developers.
public interface ISecretFactory<T>
{
T Create(string param);
}
public abstract class Base<T> where T : Base<T>, ISecretFactory<T>
{
public T GetChild()
{
// We are sure type T always implements ISecretFactory<T>
var factory = this as ISecretFactory<T>;
return factory.Create("base param");
}
}
public class Derivative : Base<Derivative>, ISecretFactory<Derivative>
{
public Derivative()
{
}
private Derivative(string param)
{
}
Derivative ISecretFactory<Derivative>.Create(string param)
{
return new Derivative(param);
}
}
public class SecondDerivative : Derivative
{
public void F()
{
// intellisense won't show Create method here.
// But 'this as ISecretFactory<Derivative>' trick still works.
}
}
The additional object can be avoided by moving the ComplexComputation to the constructor of the base class and making the GetChild method abstract to let the deriving class pick a correct constructor there.
But how to return the computed value param in base constructor to the invoking derivate constructor? A possibility is to use the out parameter modifier. But because in C# 5.0 we are unfortunately not able to declare the variables before (or within) the base constructor call, we need to take the parameter along in the derivative constructor.
public abstract class Base<T> where T : Base<T>
{
public abstract T GetChild();
protected Base(T parent, out string param)
{
param = ComplexComputation();
}
protected Base()
{
}
}
// --- somewhere else: ---
public class Derivative : Base<Derivative>
{
public sealed override Derivative GetChild()
{
string param;
return new Derivative(this, out param);
}
public Derivative() { }
private Derivative(Derivative parent, out string param)
: base(parent, out param)
{
// some configuration
}
}
In my case I could leave the param from the constructors away, instead I stored it in a public property.
This approach except the pesky necessary hack looks relatively clean to me, but it does not “scale” when multiple overloadings of GetChild are necessary.
Maybe in C# 6.0 it is possible to declare the param directly in the base constructor invocation. https://msdn.microsoft.com/de-de/magazine/dn683793.aspx

Autofac registering specific method parameter type

I am using the Autofac IOC with construcor validation. I can't figure out how to register the classes in the IOC so that LogotypeService gets LogoImageValidator and AdService get AdValidator injected in it's constructors.
I don't want to specify which instance of SomeClass that should be injected.
I have:
One validation interface (IImageValidator)
One base class for the common validation logic (ImageValidatorBase)
Two subclasses which holds specific valiation logic (LogoImageValidator and AdImageValidator)
One service interface (IService)
Two services which each should use different subclasses for validation. (LogotypeService should use LogoImageValidator) and (AdService should use AdValidator)
Interface
public interface IImageValidator
{
bool ValidFileSize();
}
Base class:
public abstract class ImageValidatorBase : IImageValidator
{
//constructor omitted
Public abstract ValidFileSize()
{
//shared code
}
}
Subclass LogoImageValidator
public class LogoImageValidator : ImageValidator
{
//constructor omitted
public override bool ValidFileSize()
{
//class specific code
}
}
Subclass AdImageValidator
public class AdImageValidator : ImageValidator
{
//constructor omitted
public override bool ValidFileSize()
{
//class specific code
}
}
IService
public interface IService{
bool ValidFileSize();
}
LogotypeService
public class LogotypeService : IService
{
private readonly ISomeClass _someClass;
private readonly IImageValidator _imageValidator;
public LogotypeService(ISomeClass someClass, IImageValidator imageValidator)
{
_someClass = someClass;
_imageValidator = imageValidator;
}
public bool ValidFileSize()
{
_imageValidator.ValidFileSize();//use LogoImageValidator subclass here
}
}
AdService
public class AdService : IService
{
private readonly ISomeClass _someClass;
private readonly IImageValidator _imageValidator;
public AdService(ISomeClass someClass, IImageValidator imageValidator)
{
_someClass = someClass;
_imageValidator = imageValidator;
}
public bool ValidFileSize()
{
_imageValidator.ValidFileSize();//use AdValidator subclass here
}
}
Any ideas?
This appears to overlap with this question: Inject Specific Type With Autofac
The answer there suggests that different interfaces be used based on context.

How to create instance of inherited in static base method?

From an instance, I might do this.
var obj= Activator.CreateInstance(GetType());
Not sure how to get typeof of the inherited class in a static base method though.
Is this the best way forward?
public static Method<T>() where T : SomeBase, new()
You could make the base class generic and close the generic in the derived class.
public abstract class CreatorOf<T> where T : CreatorOf<T>
{
public static T Create()
{
return (T)Activator.CreateInstance(typeof(T));
}
}
public class Inheritor : CreatorOf<Inheritor>
{
public Inheritor()
{
}
}
public class Client
{
public Client()
{
var obj = Inheritor.Create();
}
}
There are some who consider this to be an "anti-pattern", but I believe there are circumstances where it is an acceptable approach.
Maybe you should better tryto use abstract factory pattern?
http://en.wikipedia.org/wiki/Abstract_factory_pattern
There is no such thing as a derived static method. So there is no way to create a static factory method that returns a different type depending on which derived class you call it on.
As Lonli-Lokli suggested, you should use the Abstract Factory design pattern.
public interface ISomething
{
void DoSomething();
}
public class SomeClass : ISomething
{
public virtual void DoSomething() { Console.WriteLine("SomeClass"); }
}
public class SomeDerivedClass : SomeClass
{
private int parameter;
public SomeDerivedClass(int parameter)
{
this.parameter = parameter;
}
public virtual void DoSomething()
{
Console.WriteLine("SomeDerivedClass - {0}", parameter);
base.DoSomething();
}
}
public interface IFactory
{
public ISomething Create();
}
public class SomeClassFactory : IFactory
{
public ISomething Create() { return new SomeClass(); }
}
public class SomeDerivedClassFactory : IFactory
{
public ISomething Create() { return new SomeDerivedClass(SomeParam); }
public int SomeParam { get; set; }
}
Pros of Abstract Factory vs static Factory methods:
It is much more flexible, allowing a new implementation of your factory logic (which can be as complicated as you want) for every implementor of the abstract factory. You could have more than one factory per class, if you wanted.
Since you aren't calling a static method, it is much easier to replace at runtime. This is quite useful for injecting mocks in unit tests.
The pros are huge. Abstract Factories are superior to static factory methods in every way, even if you could get static methods to work the way you want them to.
Cons of Abstract Factory vs static Factory methods:
Users of the abstract factory must have a factory instance to create your derived types.
You have to write a new abstract factory implementation for each derived class.
The cons are very marginal.
It is extremely easy for a user to instantiate a factory to create a single object:
MyClass myClass = new MyClassFactory().Create();
As for code duplication in the factory implementation: Saving the implementer a tiny bit of typing is pointless. It is a goal in programming to write code that can be read, understood, and easily modified. There is no programming goal to save paper or keystrokes :)

Categories

Resources