I have a "Product" base class, some other classes "ProductBookDetail","ProductDVDDetail" inherit from this class. I use a ProductService class to make operation on these classes. But, I have to do some check depending of the type (ISBN for Book, languages for DVD). I'd like to know the best way to cast "productDetail" value, I receive in SaveOrupdate. I tried GetType() and cast with (ProductBookDetail)productDetail but that's not work.
Thanks,
var productDetail = new ProductDetailBook() { .... };
var service = IoC.Resolve<IProductServiceGeneric<ProductDetailBook>>();
service.SaveOrUpdate(productDetail);
var productDetail = new ProductDetailDVD() { .... };
var service = IoC.Resolve<IProductServiceGeneric<ProductDetailDVD>>();
service.SaveOrUpdate(productDetail);
public class ProductServiceGeneric<T> : IProductServiceGeneric<T>
{
private readonly ISession _session;
private readonly IProductRepoGeneric<T> _repo;
public ProductServiceGeneric()
{
_session = UnitOfWork.CurrentSession;
_repo = IoC.Resolve<IProductRepoGeneric<T>>();
}
public void SaveOrUpdate(T productDetail)
{
using (ITransaction tx = _session.BeginTransaction())
{
//here i'd like ot know the type and access properties depending of the class
_repo.SaveOrUpdate(productDetail);
tx.Commit();
}
}
}
I don't mean to be critical, but that pattern just feels bad to me.
I've heard others say that if you're taking a type in a generic method, then you're most likely doing something wrong.
I would refactor your code by declaring a base class method to help with the SaveOrUpdate method, then have the derived classes override that method. Now when you call the base class method in the generic method, you will get the derived classes implmentation
Nooooo
If you have non generic properties (as specified in common interface contract) then you should have a common function declared in the interface that is called by SaveOrUpdate to handle this
Each instance of the common interface (ProductDetailBook, productDetail etc) will define this function differently as required by "//here i'd like ot know the type and access properties depending of the class"
You are pulling class specific code and putting it into a common function, this is the start of spaghetti code
This is one of the many reasons NOT to have generic services
If you need to know about the fields or properties of the type in order to "save or update", you could use reflection. That way, the class would remain truly generic.
If within your SaveOrUpdate method you mean to write an ever-expanding switch equivalent to:
if (it's type A) { deal with type A }
else if (it's type B) { deal with type B }
... and so on
Then you're doing it "wrong". That class is not really generic in its type parameter. It only works with the specific set of types you specified. I say "wrong" in quotes because it might be better than the available alternatives in some situations, but it's undesirable. If you have a fall-back for all other types, so it always works, then it might be an okay way to have special cases for certain types.
However, you can do such a test, or casting. With an unconstrained type parameter, T, you need to cast it to object first:
var eitherStringOrNull = (string)((object)somethingOfTypeT);
With the as keyword you shouldn't need that extra cast to object.
var eitherStringOrNull = somethingOfTypeT as string;
if (eitherStringOrNull != null)
{
.. it was a string, so we can use it as such
}
But even better, if there is a common base class, ProductDetail, for all kinds of product detail class, then use that as a constraint on T:
public class ProductServiceGeneric<T> : IProductServiceGeneric<T>
where T : ProductDetail
I think it's good practise when doing that to use a more meaningful name for the type parameter, such as TProductDetail.
If you do this, then the compiler should let you "cast down" to something derived from ProductDetail, without having to cast to object first.
If I understand your question you are trying to determine what derived class you have from a function that returns a base class. You need to use the IS operator
you can see how to use the operator below.
class Base
{
}
class AB : Base
{
}
class AC : Base { }
class Program
{
static Base GetObject()
{
return null;
}
static void Main(string[] args)
{
Base B = GetObject();
if (B is AB)
{
AB DevClass =(AB) B;
}
}
}
}
Within generic methods, you have to cast with as keyword to do casts like this. There are good reasons why but its a long story...
If you do a lot with generics, read Bill Wagners "More Effective C#" for alternative ways to dealing with this more cleanly.
public void SaveOrUpdate(T productDetail)
{
using (ITransaction tx = _session.BeginTransaction())
{
ProductDetailBook bookDetail = productDetail as ProductDetailBook;
if (bookDetail != null)
_repo.SaveOrUpdate(bookDetail);
tx.Commit();
}
}
Maybe you should refactor your code as follows:
abstract class Product
{
public abstract bool CheckProduct();
}
class ProductBookDetail : Product
{
public override bool CheckProduct()
{
//Here we can check ProductBookDetail
}
}
class ProductDetailDVD : Product
{
public override bool CheckProduct()
{
//Here we can check ProductDetailDVD
}
}
public class ProductServiceGeneric<T> : IProductServiceGeneric<T> where T : ProductDetail
{
public void SaveOrUpdate(T product)
{
if (!product.CheckProduct())
{
//product checking failes. Add necessary logic here
}
}
}
This code is much more appropriate for OOP. It much simpler, it more extensible and less error prone.
P.S. Don't forget about S.O.L.I.D.
I would look up Strategy pattern and maybe use that in conjunction with your generic repository. Then you can define your strategy in some interface for your entities, which forces them to implement some method like CheckConstraints. In your generic repository you then call CheckConstraints before executing SaveOrUpdate.
Use:
if(productDetail is ProductDetailBook)
{
...
...
}
and similarly for others.
Related
The following code shows what I would like to do; that is, I would like to constrain anObject, so that it can be used as a parameter to various methods with use IInterfaceOne or IInterfaceTwo, where neither inherits from the other.
public interface IInterfaceOne { }
public interface IInterfaceTwo { }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
}
public interface IInterfaceOneAndTwo : IInterfaceOne, IInterfaceTwo { }
public class UsingImplementation
{
IInterfaceOneAndTwo anObject = (IInterfaceOneAndTwo)(new Implementation()); //fails because Implementation doesnt acctually implement IInterfaceOneAndTwo
}
This example fails however as IInterfaceOneAndTwo is an interface in its own right, and Implementation does not implement it.
I know if I used generics I could constrain them, but I am wondering, if there is a way to do this without generics?
Is there a way to say anObject shall implement IInterfaceOne and IInterfaceTwo, without using IInterfaceOneAndTwo?
Not the way you have it currently. Only generic constraints have that ability.
You could rewrite it to use generics:
public class UsingImplementation<T>
where T : IInterface1, IInterface2, new()
{
T anObject = new T();
void SomeMethod() {
anObject.MethodFromInterface1();
}
}
You can also have generic methods, not only generic classes
public void DoSomething<T>(T value)
where T : IInterface1, IInterface2
{
value.DoInterface1Things();
value.DoInterface2Things();
}
Or
public void DoSomething<T>()
where T : IInterface1, IInterface2, new()
{
T anObject = new T();
}
You can't do that in C# without generics but there is an alternative workaround to solve the problem without generics that was not mentioned here and might fit for you. This style is often used together with the IoC principle. You could inject the same object twice. Let me change your sample quite a bit...
public interface IInterfaceOne { void Hello(); }
public interface IInterfaceTwo { void World(); }
public class Implementation : IInterfaceOne, IInterfaceTwo
{
public void Hello() { };
public void World() { };
}
public class UsingImplementation
{
private readonly IInterfaceOne one;
private readonly IInterfaceTwo two;
public UsingImplentation(IInterfaceOne one, IInterfaceTwo two)
{
this.one = one;
this.two = two;
}
// do the stuff you want to do with an IInterfaceOne using field one
public DoSomeThingWithOne() { one.Hello(); }
// do the stuff you want to do with an IInterfaceTwo using field two
public DoSomeThingWithTwo() { two.World(); }
}
Then you could wire up the things this way:
var oneAndTwo = new Implementation();
var a = new UsingImplementation(oneAndTwo, oneAndTwo);
// operates on the first param (which is the same as the second)
a.DoSomeThingWithOne();
// operates on the second param (which is the same as the first)
a.DoSomeThingWithTwo();
Have a look for IoC principle (Inversion of Control) and Dependency Injection and you'll find more solutions similiar to this one.
This way you don't need to create an extra Interface combining InterfaceOne and InterfaceTwo, two.
"Incoming" generic class parameters and generic method parameters can combine types, but there is no facility for variables or fields to represent "composite" types. Further, in order to pass an object to a parameter of a generic type which combines multiple constraints, the object must be cast to a type which in fact implements all of those constraints. This can be difficult.
For example, suppose class Foo and Bar both implement Intf1 and Intf2. One wishes to write a function AddToList<T>(thing as T) where T:Intf1,Intf2. Such a function will perfectly happily accept objects of type Foo or Bar. Suppose, however, one wishes to use such a function to add all objects to the same list (which might be a mix of Foo, Bar, and any number of other types that also happen to implement Intf1 and Intf2) and then later pass those objects to a function whose parameter is likewise constrained to implement both Intf1 and Intf2. One could cast to Foo any object which happened to be a Foo, and cast to Bar any object which happened to be a Bar, but if other types are written which also handle Intf1 and Intf2, it would be difficult to deal with them.
It is possible to solve the problem, somewhat awkwardly, without using Reflection or other such tricks. Define an interface IActUpon<Base1, Base2> with a method ActUpon<thingType>ActUpon(thingType thing) where thingType: Base1, Base2. Implementations of such a method will be able to pass parameter thing to other methods requiring generic method parameter constrained to Base1 and Base2. The biggest difficulties with such an approach are that one must write separate code for each possible number of constraints, and that in many places where one would have used a lambda expression one will instead have to write an implementation of IActUpon....
If this is desirable then there has to be a logical connection between IInterfaceOne and IInterfaceTwo and the implementing class should implement the combined interface:
class Implementation : IInterfaceOneAndTwo { ... }
If this is not possible, because it's not (all) your code then you may have to rethink the UsingImplementation. It simply doesn't fit the available surface.
I have a couple of classes, all derived from the same base type.
class basetype{}
class TypeA : basetype{}
class TypeB : basetype{}
...
A number of them is stored in a list.
List<basetype> myObjects
As always, each of these types has to be handled differently. Now I have a couple of methods to handle them, and one method that takes the basetype as parameter.
HandleTypes(TypeA obj){}
HandleTypes(TypeB obj){}
HandleTypes(basetype obj)
currently, my HandleAllTypes looks like that:
string name = obj.GetType().Name
switch(name)
{
case "TypeA":
return HandleTypes(obj as TypeA);
case "TypeB":
return HandleTypes(obj as TypeB);
....
}
now this is crap. Is there a way like
HandleTypes(obj ?"as derived type"?)
Searched through MSDN and other sources, found nothing.
How about
HandleTypes( obj as dynamic );
?
I've used this a couple times when I had to deal with third-party classes. It also can be very helpful when there are a lot of derived classes.
You can easily check whether the handling function is implemented:
try {
HandleTypes( obj as dynamic )
}
catch( RuntimeBinderException ex ) {
// not implemented
}
class basetype{
public virtual void Handle(){
// do only for base type
}
}
class TypeA : basetype{
public override void Handle(){
// do only for Atype
}
}
class TypeB : basetype{
public override void Handle(){
// do only for Btype
}
}
foreach(baseType obj in myObjects)
obj.Handle()
It won't be possible to choose the correct method like that at compile time, because it won't know which one to bind to. You could possibly use reflection for it.
For splitting out types I tend to do something like this:
TypeA aRef = obj as TypeA;
if (aRef != null)
HandleTypes(aRef);
However, the ideal way would be to use inheritance and put a HandleType method on the base class, make it virtual and override it on the derived types where needed. However, sometimes this isn't an option for whatever reason.
Normally, you'd probably implement your 'HandleTypes' functionality on basetype/TypeA/TypeB, and just call obj.HandleTypes(), and let the polymorphism handle it. Any reason you can't do that?
I think what you need here is virtual methods.
Basically you declare a virtual method on your base class, called lets say DoWork().
Now you can override this virtual method on TypeA.
You can override it on TypeB as well.
If you call DoWork() on a base object, its method will be used.
If you call DoWork() on an object of typeA, its method will be used.
Basically, the correct method will be used, as long as you override it in the correct class.
More info: http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx
Here's a different way to get at what you're trying to do.
Methods:
void HandleTypes(IEnumerable<Apple> apples)
void HandleTypes(IEnumerable<Banana> banana)
void HandleTypes(IEnumerable<Orange> oranges)
void HandleTypes(IEnumerable<Fruit> fruit)
Called by:
List<Fruit> fruitbasket = GetBasket();
HandleTypes(fruitbasket.OfType<Apple>());
HandleTypes(fruitbasket.OfType<Orange>());
HandleTypes(fruitbasket.OfType<Banana>());
HandleTypes(fruitbasket.OfType<Fruit>());
Or called by:
List<Fruit> fruitbasket = GetBasket();
ILookup<Type, Fruit> fruitLookup = fruitBasket.ToLookup(x => x.GetType());
foreach(IGrouping<Type, Fruit> fruitRollup in fruitLookup)
{
switch(fruitRollup.Key.Name)
{
case "Apple" :
return HandleTypes(fruitRollup.OfType<Apple>());
break;
case "Banana" :
return HandleTypes(fruitRollup.OfType<Banana>());
break;
case "Orange" :
return HandleTypes(fruitRollup.OfType<Orange>());
break;
case "Fruit" :
return HandleTypes(fruitRollup.OfType<Fruit>());
break;
default :
return HandleTypes(fruitRollup.OfType<Fruit>());
break;
}
}
What you need is double dispatch which isn't available directly in C#. A solution based on the visitor pattern can be used to mimic double dispatch, by having basetype declare an abstract Accept method that makes a call into the visitor, where overload resultion will select the correct method.
abstract class basetype
{
//..
public abstract void Accept(Visitor v);
//..
}
class TypeA
{
//..
//..
public override void Accept(Visitor v) { v.Visit(this); }
}
abstract class Visitor
{
public abstract void Visit(TypeA a);
public abstract void Visit(TypeB b);
}
Placing your "Handling" methods in a class derived from Visitor makes it possible to have ordinary overload resolution solve the problem. In my opinion this is a cleaner design than using reflection.
What you're asking for is not possible. Method calls are resolved at compile time and do not change afterwards - but you're asking to select a particular method based on a runtime value. This would only be possible using delegates, but even with delegates, you will not be able to upcast an argument to a more derived type than the one specified in the delegate declaration.
I've been dealing a lot lately with abstract classes that use generics. This is all good and fine because I get a lot of utility out of these classes but now it's making for some rather ugly code down the line. For example:
abstract class ClassBase<T>
{
T Property { get; set; }
}
class MyClass : ClassBase<string>
{
OtherClass PropertyDetail { get; set; }
}
This implementation isn't all that crazy, except when I want to reference the abstract class from a helper class and then I have to make a list of generics just to make reference to the implemented class, like this below.
class Helper
{
void HelpMe<C, T>(object Value)
where C : ClassBase<T>, new()
{
DoWork();
}
}
This is just a tame example, because I have some method calls where the list of where clauses end up being 5 or 6 lines long to handle all of the generic data. What I'd really like to do is
class Helper
{
void HelpMe<C>(object Value)
where C : ClassBase, new()
{
DoWork();
}
}
but it obviously won't compile. I want to reference ClassBase without having to pass it a whole array of generic classes to get the function to work, but I don't want to reference the higher level classes because there are a dozen of those. Am I the victim of my own cleverness or is there an avenue that I haven't considered yet?
I suppose that your HelpMe method would be used for initializing the concrete ClassBase<T> type (a guess based on the constraints). To keep the code fully generic (if you need both T and C somewhere in the method), you probably need to keep both of the type parameters.
However, you could add a non-generic base class and then write something like this:
abstract class ClassBase {
object UntypedProperty { get; set; }
}
abstract class ClassBase<T> : ClassBase {
T Property { get; set; }
public override object UntypedProperty {
get { return Property; }
set { Property = (T)value; }
}
}
Then you could be to write the helper method like this:
void HelpMe<C>(object Value) where C : ClassBase, new() {
var n = new C();
c.UntypedProperty = Value;
}
Depending on your specific scenario, something along these lines might work and make the code a little bit simpler. However, you need to modify the base class to make this possible.
Generics do have a tendency to propogate through the code, and they're seldomly used as "mixin" classes for that reason.
Thomas mentioned the one possibility of introducing an equivalent non-generic API. I would prefer revisiting the design and making these base classes non-generic if possible while maintaining full type safety. Whether or not this is actually possible is determined by your requirements.
There is one other possibility short of a re-design (or API duplication): dynamic. If you're willing to lose IntelliSense in your helper methods (and are willing to pay a very, very small runtime performance penalty), you can use dynamic in your helper method:
class Helper
{
void HelpMe<C>(object Value)
// where C : ClassBase<T>, new() // no longer needed, but should be documented
{
dynamic cObj = Activator.CreateInstance<C>(); // instead of "new C()"
cObj.PropertyDetail = ...;
cObj.Property = ...;
...
}
}
without having to pass it a whole array of generic classes to get the function to work
A small change might ease these calls. Move repeatedly specified types to the generic declaration of the class.
//before
Helper x = new Helper();
x.HelpMe<MyClass, string>(x);
x.HelpMe<MyClass, string>(y);
//after
Helper x = new Helper<string>();
x.HelpMe<MyClass>(x);
x.HelpMe<MyClass>(y);
//the change
class Helper<T>
{
void HelpMe<C>(object Value)
where C : ClassBase<T>, new()
{
DoWork();
}
}
I often find myself in a situation where I create a generic interface or class and then want to use different versions of this class or interface in a non generic way. For example I may have an interface like this:
interface ICanCreate<T>
{
T NewObject();
}
Which allows a class to be a factory for that type. I then want to register these with a general factory class, so I try to write something like this:
public class Factory
{
private Dictionary<Type, ICanCreate> mappings; // what do I put here????
public void RegisterCreator<T>(ICanCreate<T> creator)
{
}
public T Create<T>()
{
}
}
In the dictionary which type do I use for my value? I don't know if I am missing some sort of design principle and I am aware that this has a lot to do with co(ntra?)variance. Any help or ideas would be much appreciated.
You either have to just use object in your dictionary declaration (it's all private, and you can verify that you'll never put the wrong kind of thing in there) or declare a non-generic ICanCreate interface which ICanCreate<T> extends.
Basically you want a type relationship which can't be expressed in C# - and whenever that happens, you end up with a slightly unpleasant solution, but it looks like you can isolate the ugliness here (i.e. keep it within the single class).
Interestingly, this is a problem that is solved in C# 4.0:
public interface ICanCreate<out T> // covariant
{
T NewObject();
}
public class Factory
{
private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>();
public void RegisterCreator<T>(ICanCreate<T> creator) where T:class
{
mappings[typeof(T)] = creator;
}
public T Create<T>()
{
ICanCreate<object> creator = mappings[typeof(T)];
return (T) creator.NewObject(); // I do not think you can get rid of this cast
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
I can do
public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T
How would i do the second? if i cannot do that, how can i do something like
public class MyGenericClass <T>
{
T obj;
//have all MyGenericClass.XYZ call obj.XYZ
}
This is not possible, because depending on what type T is, the public interface of MyGenericClass would change.
If you have lots of different classes that all expose the same interface, you could declare MyGenericClass to expose that interface, and in the implementation of all of the functions delegate the calls to obj
The specific question, why can't you do this:
public class MyGenericClass<T> : T
And you can do this:
public class MyGenericClass<T>
{
T obj;
}
The reason is that the CLR likes to be able to compile a single version of the code for MyGenericClass that will work for any reference type specified for T.
It can do this for the second case, because it can quietly replace T with object and insert appropriate casts, roughly equivalent to:
public class MyGenericClass
{
object obj;
}
But for the inheritance version, that trick doesn't work.
Also, many useful facilities would be impossible to describe through interface constraints. When you inherit from a type, you can do a lot more than just call methods on it - you can override them as well. Consider this hypothetical example:
class MyBase
{
public virtual void MyVirtual() { }
}
class MyGenericDerived<T> : T
{
public override void MyVirtual()
{
Console.WriteLine("Overridden!");
}
}
MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();
What I want to do there is something like a "mix-in", where MyGenericDerived supplies definitions for virtual functions in whatever base it is applied to. But how does the compiler know that T will have a method called MyVirtual that can be overridden? I'd need to put a constraint on T. How would I express that through interfaces? It's impossible. Using interfaces to describe constraints isn't an adequate solution once you allow inheritance from type parameters. So that's another reason why it doesn't exist in the language today.
You could do something like
public interface IXyzable { void xyz(); }
public class MyGenericClass<T> : IXyzable where T : IXyzable {
T obj;
public void xyz() {
obj.xyz();
}
}
Edit: Now I understand the question
You'll need all your possible T's to implement some interface so that you know that obj.XYZ() makes sense, then you can do
public interface Ixyz
{
void XYZ();
}
public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
T obj;
public MyGenericClass()
{
obj = new T();
}
public void XYZ()
{
obj.XYZ();
}
}
I've made MyGenericClass implement Ixyz too since it obviously does expose the right method, but maybe that's best left out since it allows
var x = new MyGenericClass<MyGenericClass<SomeClass>>();
which is unlikely to ever be a good idea.
This is pretty much duck-typing, but you could use reflection.
When you create the generic class with a reference to the obj, use reflection to try and find a method with the right signature. As long as you store a reference to the method, performance won't be too bad.
class BaseGeneric<T>
{
private T obj;
private MethodInfo mi;
private const string MethodNameOfInterest = "Xyz";
public BaseGeneric(T theObject)
{
this.obj = theObject;
Type t = obj.GetType();
mi = t.GetMethod(MethodNameOfInterest);
}
public void Xyz()
{
mi.Invoke(obj, null);
}
}
Of course, you would need to add a lot more for error checking and such, but that is the gist of what you could do. Also, don't forget to add the System.Reflection namespace to your using clause.
The .NET type system won't allow type declarations of the form you're attempting. One reason why this is disallowed should be intuitive: how would MyGenericClass<T> act when T is a sealed class (e.g. System.String)?
If you absolutely need this functionality (and you know that the type T you'll be using isn't sealed), you can generate proxies at runtime using the classes in the Reflection.Emit namespace. It may also be possible to achieve this effect using AOP tools like PostSharp.
What about this:
class BaseClass<T>
{
public T property { get; set; }
}
class GenericClass<T> : BaseClass<T>
{
}
class Program
{
static void Main(string[] args)
{
GenericClass<int> l = new GenericClass<int>();
l.property = 10;
}
}
This achieves what you want to do?