Detecting Interfaces in Generic Types - c#

I have a method:
public void StoreUsingKey<T>(T value) where T : class, new() {
var idModel = value as IIDModel;
if (idModel != null)
Store<T>(idModel);
AddToCacheUsingKey(value);
}
that I would like to optionally call the following method, based on the value parameter's implementation of IIDModel.
public void Store<T>(T value) where T : class, IIDModel, new() {
AddModelToCache(value);
}
Is there a way to tell Store<T> that the value parameter from StoreUsingKey<T> implements IIDModel? Or am I going about this the wrong way?
Rich
Answer
Removing the new() constraint from each method allows the code to work. The problem was down to me trying to pass off an interface as an object which can be instantiated.

You already are. By putting the IIDModel constraint on the Store<T> method, you're guaranteeing, that the value parameter implements IIDModel.
Oh, ok I see what you're saying now. How about this:
public void StoreUsingKey<T>(T value) where T : class, new() {
if (idModel is IIDModel)
Store<T>((IIDModel)idModel);
AddToCacheUsingKey(value);
}
Edit yet again: Tinister is right. This by itself won't do the trick. However, if your Store method looks like what Joel Coehoorn posted, then it should work.

public void Store(IIDModel value) {
AddModelToCache(value);
}

Removing the new() constraint from each method allows the code to work. The problem was down to me trying to pass off an interface as an object which can be instantiated.

Related

What creational pattern I should use?

My program have two classes; both derive from same base class.
class A : MyBase
{
internal A(InitVal initVal)
}
class B : MyBase
{
internal B(InitVal initVal)
}
InitVal is another class which is injected through constructor. This class is for internal usage. Due to internal constructor, user cannot create instance of class A and B directly. Instead, I created method which creates these objects.
class Initiator
{
InitVal initVal;
public T CreateObject<T>(ObjectInstance objectInstance) where T : MyBase
{
MyBase myBase = null;
switch(objectInstance)
{
case ObjectInstance.A:
myBase = new A(initVal);
break;
case ObjectInstance.B:
myBase = new B(initVal);
break;
}
return (T)myBase;
}
...
}
ObjectInstance is enum in above code.
This works without problem but I am sure you have never seen such ugly code earlier.
Please suggest creational pattern I should use. I want to remove ObjectInstance enum without changing functionality. It will cleanup much.
I tried Creational Patterns mentioned on dotfactory.
Factory Method and Abstract Factory does not look proper in this case.
My code even though look ugly, it is very simple to read and understand. I tried implementing patterns mentioned above which increases code complexity. So this is also my criteria while choosing answer.
I cannot change anything in code except Initiator class. All other classes are not accessible to me for edit.
Edit 1: Why above code is ugly in my view
1) While calling CreateObject method, user have to specify type of the object twice.
A a = initiator.CreateObject<A>(ObjectInstance.A);
First for T generic value and second to enum value.
I want to avoid this.
2) As user has to specify type of object twice, there are chances of mistake.
A a = initiator.CreateObject<A>(ObjectInstance.B);
In above code, enum value and generic value are different.
This is not allowed and will be a problem.
With my code, I cannot avoid this.
That is why; I am looking for pattern that suits my case without increasing complexity.
If I remove necessity of enum somehow, code will be lot better.
If I can change signature of CreateObject to following, it will be lot better.
public T CreateObject<T>() where T : MyBase
But, I am not sure how I will implement this method to create proper instances.
It doesn't look to me like you are getting any advantage from trying to make this generic. You needs to know the concrete type of the returned value at the call site.
Therefore why not keep things simple and just do this?
public class Initiator
{
InitVal initVal;
public A CreateA()
{
return new A(initVal);
}
public B CreateB()
{
return new B(initVal);
}
}
As you specified the method as generic one, I expect you might actually know the type you want to get already during the compilation time.. so I'd go for something like this:
class Initiator
{
public T CreateObject<T>(ObjectInstance objectInstance) where T : MyBase, new()
{
T newInstance = new T();
newInstance.Value = initVal;
return newInstance;
}
...
}
now you can call it as:
A myAInstance = initiator.CreateObject<A>();
MyBase myAInstance = initiator.CreateObject<A>(); //this also works
To make it work you need to specify an internal parameterless constructor in your classes and specify interface for the Value property or whatever you would set now in your current constructor.
class MyBase{
InitVal Value { get; set;} //this allows construction of the object with parameterless constructor
...
}
This is not only cleaner and shorter, but also less error prone, as you dont need to edit both enum and method body every time new type is added. It gives less flexibility for child-type specific logic, though.
NOTE: If you really want to have constructor with parameters as you have now you still can go for this approach but you'd need to use reflection (check Activator) or lambdas.
Of course this makes only sense if you can decide on the type during compilation time or you if you just want to delegate this decition to a 3rd party library, eg:
switch(chosenType){
case ObjectInstance.A:
instance = initiator.CreateObject<A>();
...
Otherwise, simply leave it as it is, its a FactoryMethod pattern more or less and it does the job. Just that the generic parameter in it... seems to be quite useless then. I would remove it and change return type to MyBase, as user won't be able to specify T anyway.
One last option is to simply create a separate method for each type, this is clean, flexible, gives a lot of options for customization, but sucks if you need to repeat a lot of shared logic and you need to add a new one for each next type. Simply:
A CreateObjectA(InitVal initValue){
return new A(initValue);
}
B CreateObjectB(InitVal initValue){ ...
One obvious problem with your code is the enum, which is unnecessary, because typeof(T) already gives you the appropriate type:
class Initiator
{
readonly Dictionary<Type, Func<MyBase>> _dict = new Dictionary<Type, Func<MyBase>>();
internal Initiator(InitVal initVal)
{
// initialize your "service locator".
// it's cool that different types can have different constructors,
// and people who call CreateObject don't need to know this.
_dict[typeof(A)] = (Func<MyBase>)(() => new A(initVal));
_dict[typeof(B)] = (Func<MyBase>)(() => new B(initVal, someOtherStuff));
}
public T CreateObject<T>() where T : MyBase
{
var ctor = _dict[typeof(T)];
return (T)ctor();
}
}
Alternatively, if you don't know the type, you can pass the enum, but then the return type should be an interface/base class (preferably interface):
// this is more likely, you probably don't need a generic method
public IMyBase CreateObject(ObjectInstance objectInstance)
{
// the dictionary would map enum value to Func<IMyBase>, of course
var ctor = _dict[objectInstance];
return ctor();
}
And now you have a simple "poor man's" DI class called Initiator, so I wonder if your DI framework (the one which injected InitVal) can also inject A and B instances. Which is probably true, since DI purists will tell you there is no place for factories and the new keyword in your code.
Btw, ObjectInstance is a really, really bad name for an enum.
I did it in following way:
class A : IMyType
{
internal A(InitVal initVal)
}
class B : IMyType
{
internal B(InitVal initVal)
}
class Initiator
{
InitVal initVal = .....;
public T CreateObject<T>() where T : IMyType
{
IMyType myType = null;
if(typeof(T) == typeof(A))
myType = new A(initVal);
else if(typeof(T) == typeof(B))
myType = new B(initVal);
else
throw new MyException("Type is not configured.");
return (T)myType;
}
...
}
This resolves the problems I mentioned in my question. But, it creates new problem. This violates open-close principle of SOLID. Last else block handles the manual mistake if any. Anyway, it just works for my specific case; not recommended generally.

Error trying to cast to generic type: redundant cast

I'm having a generic function that returns a new instance of a subclass of AnyListVM implemented basically like this:
public TListVM MakeListVM<TListVM>()
where TListVM : AnyListVM
{
TListVM listVM;
switch(typeof(TListVM).ToString())
{
case nameof(EventListVM):
listVM = new EventListVM();
// some more init stuff
break;
// some more similar cases
default:
throw new NotImplementedException();
}
return listVM;
}
The two involved classes look currently like that, without any meaningful implementation yet:
public abstract class AnyListVM
{
}
public class EventListVM : AnyListVM
{
}
Now Visual Studio underlines my new EventListVM() and nags that it can't implicitly convert EventListVM to TListVM.
Okay, so I thought I simply add an explicit cast:
listVM = (TListVM)new EventListVM();
But nope. Now Visual Studio underlines it again and says that it's a redundant cast. The offered automatic fix would be to remove the cast again. Infinite loop.
What is going wrong here, why am I not allowed to do this cast, explicitly or implicitly?
There's one glaring thing in your implementation that is incorrect, which other's have pointed out but haven't addressed satisfactorily. If you intend to instantiate TListVM, then you need to change two very important parts. First the new code listing:
public TListVM MakeListVM<TListVM>()
where TListVM : AnyListVM, new()
{
TListVM listVM = new TListVM();
EventListVM evtList = listVM as EventListVM;
if (evtList != null)
{
// set evtList properties. You can't change
// the instantiation method.
}
// repeat for other constructs.
return listVM;
}
Now, to expound a bit. The generic where clause needs to specify that you intend to create the TListVM with a parameterless constructor. To do that, you need to specify new() as a generic constraint.
This greatly simplifies your implementation which only knows there is something called TListVM that has a base class of AnyListVM and has a constructor with no parameters. There's no need for a complicated switch statement, or using the Activator.
Any time you are dealing with generics, work with your generic parameter directly.
Based on further information, the switch statement is still the wrong tool. Generics necessarily constrain how you work with your object. You can't change the constructor, but you can specialize how you set properties after the object is instantiated.
Above I changed the listing to show how to set those properties directly.
If, instead you were dead set on having different constructors, etc. then you would have to approach it differently. You would have to return the base class and not TListVM.
public AnyListVM MakeListVM<TListVM>()
where TListVM : AnyListVM
{
return MakeListVM(typeof(TListVM)) as TListVM;
}
private AnyListVM MakeListVM(Type listVM)
{
AnyListVM listVM;
switch(listVM.ToString())
{
case nameof(EventListVM):
listVM = new EventListVM();
// some more init stuff
break;
// some more similar cases
default:
throw new NotImplementedException();
}
return listVM;
}
The generic helper method lets you wrap your more generic factory method so it has the signature you want, without causing compile errors.
You can't guarantee that EventListVM will convert to TListVM as according to your generic restriction, one is allowed to pass ANY inherited class of AnyListVM, which may or may not be EventListVM. Example, if the caller of this method did this:
AnyListVM vm = MakeListVM<SomeOtherListVMConcrete>();
It would fail, but shouldn't.
I believe what you really want is to cast your EventListVM to AnyListVM, the actual base type rather than the generic.
AnyListVM listVM = new EventListVM();
Still, if you are always returning an instance of EventListVM, I'd consider removing the generic clause all together and updating the signature to have a return type of EventListVM.
To make your problem more obvious, consider a base class and two children:
public class Base { } //AnyListVM
public class Child1 : Base{ } //EventListVM
public class Child2 : Base{ } //OtherListVM
now your method looks like:
public T Get<T>() where T : Base
{
//code
T item = new Child1();
//more code
}
Imagine I send in Child2, which is perfectly valid from the method signature. The method's code now looks like:
Child2 item = new Child1();
which of course is going to be invalid at compile time.

C# how to force generic argument to be type

i have generic method. i want generic method to limit one type. problem is derived type not to be allowed - i do not want this. example codes:
public static T Generate<T>(T input)
where T : Operation // ALLOWS BinaryOperation - NOT WANT THIS
{
//...
}
how to do what I request?
problem is derived type not to be allowed
There is no way to enforce this constraint, without checking it at runtime. Doing so would be a violation of the Liskov Substitution Principle, which states that any type should allow you to pass in a derived type without restriction.
If you must enforce this, it will only work with a runtime check, like:
public static T Generate<T>(T input)
where T : Operation // ALLOWS BinaryOperation - NOT WANT THIS
{
// Checks to see if it is "Operation" (and not derived type)
if (input.GetType() != typeof(Operation))
{
// Handle bad case here...
}
// Alternatively, if you only want to not allow "BinaryOperation", you can do:
if (input is BinaryOperation)
{
// Handle "bad" case of a BinaryOperation passed in here...
}
}
Note that, in this case, there's really no reason to make it generic, as the same code would work as:
public static Operation Generate(Operation input)
{ // ...
It's not possible to force a method to accept only one specific type like Operation if the type is not a struct or a sealed class.
Let's me show this in a example why this won't work anyway:
public void Generate<T>(Operation op)
// We assume that there is the keyword "force" to allow only Operation classes
// to be passed
where T : force Operation
{ ... }
public void DoSomething()
{
Generate(new BitOperation()); // Will not build
// "GetOperation" retrieves a Operation class, but at this point you dont
// know if its "Operation" or not
Operation op = GetOperation();
Generate(op); // Will pass
}
public Operation GetOperation() { return new BitOperation(); }
As you can see it will be easy to pass a BitOperation even when there is a restriction.
Solution
There is only one solution beside the others mentioned above ( struct, sealed ): Runtime Check.
You can write yourself a little helper method for this.
public class RuntimeHelper
{
public static void CheckType<T>(this Object #this)
{
if (typeof(T) != #this.GetType())
throw new ....;
}
}
Usage
public void Generate(Operation op)
{
op.CheckType<Operation>(); // Throws an error when BitOperation is passed
}
Little Note
If you want to speed up the helper you could use a generic class RuntimeHelper<T> with a static readonly type variable which has the type of T.
When you're doing this you cannot longer use extension methods so the call would look like this:
RuntimeHelper<Operation>.CheckType(op);

Code syntax explaination help

I am learning WPF and there's a piece of code which I don't quite understand the method declared with constraints:
public static T FindAncestor<T>(DependencyObject dependencyObject)
where T : class // Need help to interpret this method declaration
I understand this is a shared method and T has be a class but what is what is 'static T FindAncestor'? Having troubles interpreting it as a whole. Thanks!
Code:
public static class VisualTreeHelperExtensions
{
public static T FindAncestor<T>(DependencyObject dependencyObject)
where T : class // Need help to interpret this method
{
DependencyObject target = dependencyObject;
do
{
target = VisualTreeHelper.GetParent(target);
}
while (target != null && !(target is T));
return target as T;
}
}
The static keyword in front means that you do not have to instantiate VisualTreeHelperExtensions in order to call the FindAncestor method. You can say:
VisualTreeHelperExtensions.FindAncestor<MyClass>(myObj);
Where myObj is a DependencyObject. The where, as you said, makes sure that T (MyClass in this case) is indeed a class
For convenience, Methods like this can be declared like this:
public static T FindAncestor<T>(this DependencyObject dependencyObject)
where T : class // Need help to interpret this method declaration
Which would allow you to call the method like so:
myObj.FindAncestor<MyClass>();
Effectively adding a method to your DependencyObject after the fact.
The T is a placeholder for a type - what is known as a generic. The where clause is a generic constraint that requires reference types.
Hope I understand your question.
It's a declaration of public static function.
If it's not you're asking for, please explain better.
It means that it is a static method (you can call it without an instance of the class created) that returns an object of type T. FindAncestor is the name of the method.

Tracking instances with generics and supporting subclasses

I've defined the following generic class
public class ManagedClass<T> where T : ManagedClass<T>
{
static ManagedClass()
{
Manager = new ObjectManager<T>();
}
public static ObjectManager<T> Manager { get; protected set; }
public ManagedClass()
{
Manager.Add( (T)this );
}
}
The idea is that I can use it like so:
class Product : ManagedClass<Product> {}
Now I can do something to the 7th product created like so:
Product.Manager.GetById(7).DoSomething();
The problem comes in if i try to use a derived class:
class ExtendedProduct : Product {}
now ExtendedProduct.Manager has a list of 'Products', and if i want to use a new function that I have added to ExtendedProduct (DoSomethingElse), I have to cast the object I get back like so:
((ExtendedProduct)ExtendedProduct.Manager.GetById(7)).DoSomethingElse();
This is a bit ugly, and the whole point of using generics for this is to avoid casting. I suppose I could add a static constructor to the derived class to set Manager = new ObjectManager() and add a new Manager.addObject( this ) in the derived class constructor, but It seems like there should be some better way of doing this using generics. Any suggestions?
The problem is that ExtendedProduct.Manager is the same thing as Product.Manager; the manager object can't act differently depending on where it's accessed from.
A couple of possibilities I can think of:
Hide the typecast inside the GetById method by making it generic:
Product.Manager.GetById<ExtendedProduct>(7).DoSomethingElse();
Use one ObjectManager instance per subclass, connecting them privately if needed
Option 1 reminds me of NHibernate's ICriteria interface. It's effectively the same as a typecast, but a little harder to accidentally break.
Really what you're running into is a weakness with Generics. Once your class has resolved what type it's using for generics, you're somewhat restricted in what you can do.
Normally, I'd say Dependency Injection would be a savior here, but since the problematic method is static, that muddies up the waters.
I'd say the best thing is to have the ObjectManager class do the work for you:
static public class ObjectManager<T>
{
... the code that already exists in ObjectManager ...
static public U GetById<U>(long id)
{
object obj = GetById(id);
if (obj is U)
return (U)obj;
return default(U);
}
}
Then, in your code:
ExtendedProduct.Manager.GetById<ExtendedProduct>(7).DoSomethingElse();
It's not really tons more elegant than casting, but may be one of the only solutions using Generics.

Categories