Handle any type in method - c#

I have two classes.
public class Handler
{
delegate T ReturnDelegate();
public T HandleReturnMethod(ReturnDelegate d)
{
DoSomething(); //some other stuff
return d();
}
}
public partial class Test
{
protected int Id
{
get
{
return new Handler().HandleReturnMethod(delegate()
{
int id = 1;
return id;
});
}
}
}
I want to be able to handle any Type in the Handler class. But 'T' seems not to work, int cannot be converted to it.
If there is a better approach or something is wrong here, please comment.

You need to create the delegate type and method to use generics. Personally, I would use a standard delegate for this:
public T HandleReturnMethod<T>(Func<T> d)
{
DoSomething(); //some other stuff
return d();
}
Given the above, your code should work:
protected int Id
{
get
{
return new Handler().HandleReturnMethod(() =>
{
int id = 1;
return id;
});
}
}

The reason your code wasn't working is because int ( Int32 ) is a structure not an object which is the reason it cannot normally be nullable
unless you declare it as int? num = null;
If I am not mistaken only an object can have a Type ( both an object and a Type are classes ) not a structure. All classes are based on the object class ( which is the reason a collection that isn't a generic ( i.e. Type t ) elements are objects.
http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=VS.100).aspx
http://msdn.microsoft.com/en-us/library/ah19swz4.aspx
http://msdn.microsoft.com/en-us/library/ah19swz4(v=VS.100).aspx
http://msdn.microsoft.com/en-us/library/system.int32.aspx
http://msdn.microsoft.com/en-us/library/system.type.aspx
http://msdn.microsoft.com/en-us/library/system.object.aspx

Related

C# Generic type comparison

I have this code:
public class myList<T> where T : struct
{
public int number { get; set; }
}
public class TypeTest
{
public static int GetNumber(object x)
{
// if (x.GetType() == typeof(myList<>)) // this works BUT I want to use is
if (x is myList<>) // how is the correct syntax for this?
{
int result = ((myList<>)x).numb; //does not compile
return result;
}
return 0;
}
}
But some generic syntax issues.
Question: What is the correct Syntax for this?
It would be nice to re-declare your method as a generic one:
public static T GetNumber<T>(myList<T> myList) where T : struct
Doing so you would avoid any casts and the method's body would become one-liner as below:
return myList?.numb ?? 0;
You can check if the object is of your open generic type as explained in Testing if object is of generic type in C#, and then get the property named "number" from the actual type:
var typeOfX = x.GetType();
if (typeOfX.GetGenericTypeDefinition() == typeof(myList<>))
{
var numberProperty = typeOfX.GetProperty("number");
var propertyValue = numberProperty.GetValue(x);
return (int)propertyValue;
}
Do note that this code lacks any error handling, such as missing property or a property not of the expected type. That's the price you pay for being forced to use reflection.

using dynamic keyword to cast to a value type...throws exception

Sorry for the long question :
I have some classes that all have InnerObject as a property.
public class MyInt
{
int InnerObject;
}
public class MyLong
{
long InnerObject;
}
public class MyString
{
string InnerObject;
}
and so on ...
Please don't tell me I can use generics, or Don't ask me why I need these classes. Please read my question.
I have a some class called Foo that has a method called ProcessSomething :
public class Foo
{
void Process(MyInt value)
{
...
}
}
Now I have a framework code where I want to write some code like this -
I want to write code like this :
int myValue = 100;
MyInt myInt = new MyInt();
myInt.InnerObject = myValue;
myFoo.Process(myValue );
SO far so good but I have many different types of classes and their functions where I may have to pass MyString, MyLong etc....
So to ease this I tried to create a Utility class like this :
public static class MyTypes
{
public static dynamic Convert<T>(T i)
{
dynamic x = new ExpandoObject();
x.InnerObject = i;
return x;
}
}
My intention was that I could write code like this :
myFoo.Process(MyTypes.Convert<int>(myValue));
All this code compiles ,as expected, but at runtime I get an exception when I the above line is executed .
Cannot implicitly convert type 'System.Dynamic.ExpandoObject' to 'iInt32'
When I try to modify my Convert method to this :
public static K Convert<T,K>(T i)
{
dynamic x = new ExpandoObject();
x.InnerObject = i;
return (K)x;
}
and call it like this ( even though I don't like it, but I tried to see if I can make it work)
myFoo.Process(MyTypes.Convert(myValue));
I still get the exception :
Cannot convert type 'System.Dynamic.ExpandoObject' to 'iInt32'
Clearly I am not understanding something..Any help in clarifying my understanding would be much appreciated.
Don't create ExpandoObject, it's not MyInt, MyLong, etc., so it cannot be cast to these classes.
You can add a new constraint to MyTypes.Convert<T>, and use new T() to create an object to return:
public static K Convert<T,K>(T i) where K : new()
{
dynamic x = new K();
x.InnerObject = i;
return (K)x;
}
I'm not sure I understand what you are trying to accomplish or if it's possible, but I can shed some light on the problem.
dynamic x = new ExpandoObject();
x.InnerObject = i;
return (K)x;
When you invoke this code using int for the generic type parameter K, then the last line will attempt to cast an ExpandoObject to an int. There's no such conversion defined, so it fails.
Is there some reason you can't use myFoo.Process(new MyInt(...))?

How can I make this code with enumerations generic?

I am creating the wrapper POCO classes for ENUM in Entity Framework 4 as mentioned here. I have created the wrapper for the enum as follows
public class PriorityWrapper
{
private gender _t;
public int Value
{
get
{
return (int)_t;
}
set
{
_t = (gender)value;
}
}
public gender EnumValue
{
get
{
return _t;
}
set
{
_t = value;
}
}
public static implicit operator PriorityWrapper(gender p)
{
return new PriorityWrapper { EnumValue = p };
}
public static implicit operator gender(PriorityWrapper pw)
{
if (pw == null) return gender.Male;
else return pw.EnumValue;
}
}
But I also have other ENUM apart from gender as mentioned above. Can I use generics here so I can use the same code for all ENUM occurrences.
I am new to generics, so need help from experts.
You cannot use enums as generic constraints, instead you can use.
public class EnumWrapper<T>
{
public static int Num = 1;
private T _t;
public T EnumValue
{
get
{
return _t;
}
set
{
_t = value;
}
}
public void Assign<U>(U inn) where U : struct, T
{
if (typeof(T).IsEnum)
{
EnumValue = inn;
}
}
}
and invoke it like this
var agen = new EnumWrapper<gender>();
gender g=new gender() ;
agen.Assign (g);
EDIT: Assign() is a dummy method. My intention was to show how to use enum as generic constraint.
It is not possible to have generic conversion operators. So, there can't be exact generic equivalent for above code. Besides, one cannot mention enum as generic type constraint, so casting within property implementation is also not possible (or may need some other constraint (possibly interface) to work that may result in boxing/unboxing). In short, IMO, having generic solution with reasonable performance may not be feasible.
I would suggest that you try using code generation (look at T4 templates) for creating your wrapper classes. T4 is pretty simple - refer here for few links: http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

Derived interface from generic method

I'm trying to do this:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
But getting a compiler error: Canot convert type 'GenericIntf.FabInfo' to T
How do I fix this?
thanks
Sunit
Assuming all IVirtualInterface implementations will have a default constructor (as in your example), you can do this instead:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
EDIT:
Exactly what you're trying to achieve is difficult to determine from the code you've posted. Why isn't VirtualInterface static (implies all business objects inherit this method which seems odd)? If you need o be able to parameterised constructors for your IVirtualInterface implementations, where would those parameter values come from (you're not passing any into the VirtualInterface method)?
If you just want to avoid cluttering up intellisense (a poor reason for trying something like this IMHO) but also want to maintain support for parameteried constructors, then how about this:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
With usage:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
Overall though, and without enough information to make a solid judgement, I'd have to say that this smells.
The fact that T and FabInfo both implement IVirtualInterface does not mean you can perform a cast between the two types. For example if T is CoatInfo, then it is not compatible type with FabInfo.
Interfaces allow you to treat different objects as similar types based on the methods they provide. However, this does not mean that you can perform casts between these two types as their actual implementation can vary greatly.
Edit: After re-reading your method again, I see that you are checking the type first. The problem is that the compiler doesn't know you are performing that logic before you try to make that cast. If you are writing a generic method and are checking the type of T, you are likely misusing the concept of generics. See the other answers for the way you should be creating new instances of T.
You can get around this error by first casting to object before casting to T e.g.
return (T)(object)oFI;
and similarly for CoatInfo
However I think switching on a generic type is an abuse, since if you want a limited number of possible return values, you could make the options explicit e.g.
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}

C#: Declaring and using a list of generic classes with different types, how?

Having the following generic class that would contain either string, int, float, long as the type:
public class MyData<T>
{
private T _data;
public MyData (T value)
{
_data = value;
}
public T Data { get { return _data; } }
}
I am trying to get a list of MyData<T> where each item would be of different T.
I want to be able to access an item from the list and get its value as in the following code:
MyData<> myData = _myList[0]; // Could be <string>, <int>, ...
SomeMethod (myData.Data);
where SomeMethod() is declared as follows:
public void SomeMethod (string value);
public void SomeMethod (int value);
public void SomeMethod (float value);
UPDATE:
SomeMethod() is from another tier class I do not have control of and SomeMethod(object) does not exist.
However, I can't seem to find a way to make the compiler happy.
Any suggestions?
Thank you.
I think the issue that you're having is because you're trying to create a generic type, and then create a list of that generic type. You could accomplish what you're trying to do by contracting out the data types you're trying to support, say as an IData element, and then create your MyData generic with a constraint of IData. The downside to this would be that you would have to create your own data types to represent all the primitive data types you're using (string, int, float, long). It might look something like this:
public class MyData<T, C>
where T : IData<C>
{
public T Data { get; private set; }
public MyData (T value)
{
Data = value;
}
}
public interface IData<T>
{
T Data { get; set; }
void SomeMethod();
}
//you'll need one of these for each data type you wish to support
public class MyString: IData<string>
{
public MyString(String value)
{
Data = value;
}
public void SomeMethod()
{
//code here that uses _data...
Console.WriteLine(Data);
}
public string Data { get; set; }
}
and then you're implementation would be something like:
var myData = new MyData<MyString, string>(new MyString("new string"));
// Could be MyString, MyInt, ...
myData.Data.SomeMethod();
it's a little more work but you get the functionality you were going for.
UPDATE:
remove SomeMethod from your interface and just do this
SomeMethod(myData.Data.Data);
Delegates can really help simplify this, and still keep things type-safe:
public void TestMethod1()
{
Action<SomeClass, int> intInvoke = (o, data) => o.SomeMethod(data);
Action<SomeClass, string> stringInvoke = (o, data) => o.SomeMethod(data);
var list = new List<MyData>
{
new MyData<int> { Data = 10, OnTypedInvoke = intInvoke },
new MyData<string> { Data = "abc", OnTypedInvoke = stringInvoke }
};
var someClass = new SomeClass();
foreach (var item in list)
{
item.OnInvoke(someClass);
}
}
public abstract class MyData
{
public Action<SomeClass> OnInvoke;
}
public class MyData<T> : MyData
{
public T Data { get; set; }
public Action<SomeClass, T> OnTypedInvoke
{ set { OnInvoke = (o) => { value(o, Data); }; } }
}
public class SomeClass
{
public void SomeMethod(string data)
{
Console.WriteLine("string: {0}", data);
}
public void SomeMethod(int data)
{
Console.WriteLine("int: {0}", data);
}
}
Just use an ArrayList and forget the MyData<T> type.
ArrayList myStuff = getStuff();
float x = myStuff.OfType<float>().First();
SomeMethod(x);
string s = myStuff.OfType<string>().First();
SomeMethod(s);
The problem with MyData<T> is that you're expecting the compiler to check a type that is only known at runtime. Compilers check types that are known at compile time.
You can't do it the way you want.
When an instance of a generic class is initialized, it is bound to particular type. Since you want to hold objects of different types in your list, you have to create an instance bound to the least common denominator — in your case it's Object.
However, that means that Data property now will return an object of type Object. The compiler cannot infer the actual data type at compile time, so it can choose the appropriate SomeMethod overload.
You have to either provide an overload of SomeMethod that takes Object as a parameter, or remove the requirement to hold different such different types in your collection.
Or you can go with a standard IEnumerable collection (like Array) and use the OfType<> extension method to get the subset of the collection of particular type.
In that case you need MyData<object> since that is the only thing those types have in common.
You can create a generic wrapper for SomeMethod and check for the type of the generic argument, then delegate to the appropriate method.
public void SomeMethod<T>(T value)
{
Type type = typeof(T);
if (type == typeof(int))
{
SomeMethod((int) (object) value); // sadly we must box it...
}
else if (type == typeof(float))
{
SomeMethod((float) (object) value);
}
else if (type == typeof(string))
{
SomeMethod((string) (object) value);
}
else
{
throw new NotSupportedException(
"SomeMethod is not supported for objects of type " + type);
}
}
Suggested wildcards a while back here. Closed as "won't fix" :(
Generics allow you to specify one type for the whole list when you create the list, for example a list for storing int would be created like this
var myData = new MyData<int>();
If you want to store multiple types in the same generic list you can specify a common base type or interface for those types. Unfortunately in your case the only common base type for the types you want to store would be object.
var myData = new MyData<object>();
But you can just use the non-generic list for storing objects.
Inherit MyData<T> from a non-generic MyData class and make a list of that.
This way, you can't automatically resolve the overload. You have to do it manually.
abstract class MyData {
protected abstract object GetData();
protected abstract Type GetDataType();
public object Data {
get { return GetData(); }
}
public Type DataType {
get { return GetDataType(); }
}
}
class MyData<T> : MyData {
protected override object GetData() { return Data; }
protected override Type GetDataType() { return typeof(T); }
public new T Data {
get { ... }
}
}

Categories

Resources