Edit: Changed the wrong term boxing to casting.
I have the following problem:
If I create a new Delegate of type Action or Func it will be casted to a type of Delegate.
var #delegate = Delegate.CreateDelegate(type, #object, methodInfo);
But I need for a generic class the right casted object.
Consider following example:
class Example<T> {
Type GenericType() {
return typeof(T);
}
}
static Example<T> Create<T>(T #delegate) {
return new Example<T>();
}
Example.Create(#delegate).GenericType();
This will return Delegate as type, since this was the type of the casted object (#delegate).
One solution could be to cast the delegate like so:
if(#delegate is Action)
Example.Create((Action)#delegate).GenericType();
But since Delegate.CreateDelegate could also create Action or Func delegates, it is impossible to check all variations.
I can't change the generic class, so i must cast the delegate.
I hope i was able to explain my problem. I am not a native English speaker...
Edit: The Problem is that typeof(T) not return the "real" type of the object. But i'm afraid there is no solution.
What's wrong with #delegate.GetType() to get the actual type of the delegate?
Also, a side note: you are misusing the term "boxing".
If you can use .net 4.0 then your above works if you cast to dynamic
Example.Create((dynamic)#delegate).GenericType();
If you cannot, then you just have to do a little reflection and abstraction.
abstract class Example{
abstract Type GenericType();
}
class Example<T>:Example {
override Type GenericType() {
return typeof(T);
}
}
static Example Create(Delegate #delegate) {
return (Example)Activator.CreateInstance(typeof(Example<>).MakeGenericType(new []{#delegate.GetType()}));
}
To answer my own question: It is not possible. :(
Related
I've got following struct and I need to create an instance of it through System.Reflection . The big issue is that I have a generic and a non generic parameter. I have to use System.Reflection because it'll be called in a loop where T can vary. I've looked at this , but I was unabled to get it work with the second parameter (int tag). I'm sorry that I have to ask this basic question.
struct pair<T>
{
public pair(T value,int tag)
{...}
}
so I would need the magic in this:
object createPair(object o,int tag)
{
return *somemagic*
}
EDIT: the solution was making the struct public in combination with the first answer. If a struct is nested in a generic struct, both answers throw an ArgumentException, independent of the input. I'm sorry for not knowing this affect of nesting.
The reason the linked answer works is because that overload of Activator.CreateInstance hooks into parameterless, public constructors, also known as the default constructor.
However, that same method has overloads which include a signature which accepts parameters.
public object CreatePair(object t, int tag)
{
var type = t.GetType();
var targetType = typeof(Pair<>).MakeGenericType(type);
return Activator.CreateInstance(targetType, t, tag);
}
Make the input type generic using the MakeGenericType method:
object createPair(object obj,int tag) {
Type type = typeof(Pair<>);
Type genericType = type.MakeGenericType(obj.GetType());
return Activator.CreateInstance(genericType, obj, tag);
}
But I would use generics instead of reflection if it was possible.
I recently had this problem.
doSomething(typeof(int));
doSomething(typeof(MyClassA));
doSomething(typeof(MyClassB));
public void doSomething(Type _type)
{
var myGenObj = new MyGenericClass<_type>(); // Error. Really I'd want MyGenericClass<int>, MyGenericClass<MyClassA>, etc depending on what's passed in.
myGenObj.doSomeGenStuff();
// more stuff...
}
I think that this can be done with reflection somehow.. Possibly there's an easier way. I've been somewhat confused on how Type works vs Classes under the covers. Anyways thanks for any help.
Thanks.
You want Type.MakeGenericType and then Activator.CreateInstance... but then calling a method on the newly-created object will be tricky. Ideally you could have a non-generic base class or interface containing those members:
public interface IFoo
{
void CallSomeMethod();
}
public class MyGenericClass<T> : IFoo
{
...
}
// Names changed to be more conventional
public void DoSomething(Type type)
{
var genericType = typeof(MyGenericClass<>).MakeGenericType(type);
var instance = (IFoo) Activator.CreateInstance(genericType);
instance.CallSomeMethod();
}
If you do need to call a method which depends on the type parameter, you'll need to do that with reflection, or with dynamic which can streamline reflection-based code.
EDIT: As cdhowie says, if you always actually do know the type at compile-time, you can use a generic method which would make things much simpler. You'd then call the method like this:
DoSomething<int>();
DoSomething<MyClassA>();
DoSomething<MyClassB>();
Like this:
object myGenObj = Activator.CreateInstance(typeof(MyGenericClass<>).MakeGenericType(_type));
However, since the produced object is of a type that you don't know at compile-time, you can't really invoke members of the object through the generic type (except via reflection). If there is an ancestor type or implemented interface that you do know of at compile-time, you can cast to that and then invoke the member.
You might also consider wrapping this functionality in a generic method, which makes the whole thing easier to deal with:
public void doSomething<T>()
{
var myGenObj = new MyGenericClass<T>();
myGenObj.doSomeGenStuff();
}
If you have to support Type objects you can use an overload that cheats using reflection:
public void doSomething(Type _type)
{
this.GetType().GetMethod("doSomething", Type.EmptyTypes)
.MakeGenericMethod(_type)
.Invoke(this, null);
}
I need to code like this:
public static T GetValue(this SerializationInfo si, string name,Type T)
{
return (T) si.GetValue(name, typeof (T));
}
I already know that the following code can work properly
public static T GetValue<T>(this SerializationInfo si, string name)
{
return (T) si.GetValue(name, typeof (T));
}
and my code is in c#,
can anyone help?
The return type T in the first example does not refer to any valid type: T in that case is simply the name of a parameter passed to the method.
You either know the type at design time or you don't, and if you don't then your only choice is to return the type Object, or some other base type or interface.
No you cannot do that, because generics are assessed at compilation (and you are asking for dynamic generics). Can you provide some more context on the usage?
How are you getting your t parameter to pass to your desired example? If it's simply by typeof(int) as a parameter, then why not use the generic exmaple?
Consider this example:
Type t = GetTypeInfoBasedOnNameInAFile();
int a = GetValue(someSerializationInfo, "PropertyName", t);
How can the compiler know that Type t is going to be castable to int at runtime?
What you could do is have GetValue return an Object and then:
Type t = GetTypeInfoBasedOnNameInAFile();
int a = (int)GetValue(someSerializationInfo, "PropertyName", t);
But of course, if you are doing that it implies you know the expected types at compile time, so why not just use a generic parameter.
You can perhaps achieve what you are after (I'm not sure on the context/usage) by using dynamic variables.
You can do a runtime conversion to a type:
Convert.ChangeType(sourceObject, destinationType);
I believe that is the syntax. Of course, this will throw an exception if the cast is not possible.
(Thanks everyone for the answers, here is my refactored example, in turn another StackOverflow question about the Single Responsibility Principle.)
Coming from PHP to C#, this syntax was intimidating:
container.RegisterType<Customer>("customer1");
until I realized it expresses the same thing as:
container.RegisterType(typeof(Customer), "customer1");
as I demonstrate in the code below.
So is there some reason why generics is used here (e.g. throughout Unity and most C# IoC containers) other than it just being a cleaner syntax, i.e. you don't need the typeof() when sending the type?
using System;
namespace TestGenericParameter
{
class Program
{
static void Main(string[] args)
{
Container container = new Container();
container.RegisterType<Customer>("test");
container.RegisterType(typeof(Customer), "test");
Console.ReadLine();
}
}
public class Container
{
public void RegisterType<T>(string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", typeof(T), dummy, typeof(T).Name);
}
public void RegisterType(Type T, string dummy)
{
Console.WriteLine("Type={0}, dummy={1}, name of class={2}", T, dummy, T.Name);
}
}
public class Customer {}
}
//OUTPUT:
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
//Type=TestGenericParameter.Customer, dummy=test, name of class=Customer
One reason when generics are very useful is when the generic type parameter is used as the type of a parameter or as the return type of the method.
That means, you can write methods like
public T GetAs<T>(string name)
where the return type can be checked by the compiler and boxing value types can sometimes be avoided.
The caller would write:
int value = GetAs<int>("foo");
Whithout generics, you would have to write
public object GetAs(Type t, string name)
and the caller has to cast the result again:
int value = (int)GetAs(typeof(int), "foo");
A primary reason is the type safety at compile time. If you are passing two Type objects you are placing the responsibility at the developer instead of the compiler.
This is also why many IoC containers utilizes it, as your compiler will complain if an concrete type isn't inheriting the abstract type.
public void Register<TAbstract, TConcrete>() where TConcrete : TAbstract
{
}
This code will only work if TConcrete is implementing or inheriting TAbstract. If this method took two Type parameters, your method should validate this relationship.
A simple answer is type inference where possible.
If the generic type is used in the method signature, you can omit it because the type could be inferred:
void SomeMethod<T>(T x, T y) where T : IComparable<T> {
Console.WriteLine("Result: {0} to {1} is {2}", x, y, x.CompareTo(y));
}
So the usage is simplified:
SomeMethod(3, 4); // instead of SomeMethod<int>(3, 4);
SomeMethod("one", "two"); // instead of SomeMethod<string>("one", "two");
If the generic type parameter is not used in the method signature the type inference is not possible:
var emptySequence = Enumerable.Empty<int>();
I think one of the primary uses is type safety with arguments and return values. In your example case, there is not much use for generics, because the input/output types (string) do not match the generic case (customers).
A more appropriate use might be:
public T RegisterType<T>(string name)
{
T obj = new T();
obj.DoSomething();
return obj;
}
or maybe
public void DoSomething<T>(T obj)
{
//operate on obj
}
If you didn't use Generics, you'd either have to overload a method for each type you want to support, or you'd have to accept the parameter as an object and perform casting logic.
For one example, compare the code needed to create an instance of your type using the typeof option versus a generic. Or return an instance of the type. Or accept an instance of the type as an argument. Or set a property on an instance of the type.
In general, if you will be working only with the type itself you can accept a type parameter. If you want to do anything with an instance of the type, use a generic.
Another reason to use a generic is if you want to apply constraints to the type. For example, you can require the type to implement one or several interfaces, inherit another type, be a reference type or value type, have a default constructor, or some combination of the above. The compiler will enforce this so you can't build code that doesn't comply with your requirements.
I'd say the best reason is type safety, using the "where" keyword, to ensure that the generic type is of a certain type (or sub-class/implementor). Using "typeof" will let you send anything through.
I have a marker interface defined as
public interface IExtender<T>
{
}
I have a class that implements IExtender
public class UserExtender : IExtender<User>
At runtime I recieve the UserExtender type as a parameter to my evaluating method
public Type Evaluate(Type type) // type == typeof(UserExtender)
How do I make my Evaluate method return
typeof(User)
based on the runtime evaluation. I am sure reflection is involved but I can't seem to crack it.
(I was unsure how to word this question. I hope it is clear enough.)
I went this way based on some of the tidbits provided. It could be made more robust to handle multiple generic arguments on the interface.... but I didn't need it to ;)
private static Type SafeGetSingleGenericParameter(Type type, Type interfaceType)
{
if (!interfaceType.IsGenericType || interfaceType.GetGenericArguments().Count() != 1)
return type;
foreach (Type baseInterface in type.GetInterfaces())
{
if (baseInterface.IsGenericType &&
baseInterface.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition())
{
return baseInterface.GetGenericArguments().Single();
}
}
return type;
}
There is an example of doing what you describe in the MSDN documentation for the GetGenericTypeDefinition method. It uses the GetGenericArguments method.
Type[] typeArguments = t.GetGenericArguments();
Console.WriteLine("\tList type arguments ({0}):", typeArguments.Length);
foreach (Type tParam in typeArguments)
{
Console.WriteLine("\t\t{0}", tParam);
}
In your example I think you would want to replace t with this. If that doesn't work directly you may need to do something with the GetInterfaces method to enumerate the current interfaces on your type and then GetGenericArguments() from the interface type.
I read your question completely differently than the other answers.
If the evaluate signature can be changed to:
public Type Evaluate<T>(IExtender<T> it)
{
return typeof(T);
}
This doesn't require the calling code to change, but does require the parameter to be of type IExtender<T>, however you can easily get at the type T :
// ** compiled and tested
UserExtender ue = new UserExtender();
Type t = Evaluate(ue);
Certainly it's not as generic as something just taking a Type parameter, but this is a different take on the problem. Also note that there are Security Considerations for Reflection [msdn]