I haven't slept in a while so this is probably easier than I think it is.
I have a generic class that's more or less this:
public class Reference<T> where T : APIResource //<- APIResource is abstract btw
{
private T _value = null;
public T value
{
get { return _value; }
}
}
Elsewhere, in a custom serialize method, someone is passing in an object that is actually an instance of Reference<(something)>. I simply want to skip to the "value" property that every Reference<> object has, so I want to go:
string serialize(object o)
{
return base.serialize( ((Reference<>) o).value );
}
Of course, life isn't that simple because as the compiler puts it:
using the generic type "Reference<T>" requires 1 type arguments
How can I do what I want to do?
You can create a covariant generic interface with the property:
interface IReference<out T> where T : ApiResource {
T Value { get; }
}
You can then cast IReference<Anything> to IReference<object> or IReference<ApiResource>.
SLaks answer is perfect. I just want to extend it a little bit:
There are sometimes situations, where you can't substitute class with interface. Only in that cases you may want to use dynamic feature, so that you can call value property:
string serialize(object o)
{
if(typeof(Reference<>) == o.GetType().GetGenericTypeDefinition())
return base.serialize( ((dynamic)o).value );
//in your case you will throw InvalidCastException
throw new ArgumentException("not a Reference<>", "o");
}
This is just another options and I suggest to use it very carefully.
Dont forget to check whether its generic type or not ---> o.GetType().IsGenericType, before
using o.GetType().GetGenericTypeDefinition() else it throws exception..
Related
So I have a generic class, with Type as its generic parameter. In this class is a method, which has object parameter called value. Kinda like this:
public class Foo<Type> where Type : IComparable
{
public void Bar(object value)
{
DoSomething((Type)value);
}
}
As you can notice, I need to "DoSomething" with value (stored in object) that I first need to cast to Type. I even have my own overridden cast, which works on its own.
In this specific case, Type is generic, lets call it GenericType, and has this user-defined cast:
public static implicit operator GenericType<T>(T value)
{
return new GenericType<T>(value);
}
and value is an enum, lets say
public enum Number: short
{
Zero = 0,
One = 1,
Two = 2
}
The 'DoSomething((Type)value)' in this case is where Type is GenericType and value is Number.Zero. For some reason, this causes the cast to throw InvalidCastException: Specified cast is not valid. When I try it directly, i mean like..
GenericType<Number> z = (GenericType<Number>)Number.Zero;
..it works (I know, there is not explicit cast even needed). But for some reason, it does not work in the complex example I stated above. Can anyone help me understand and potentially fix that?
Why not just let your class use the generic type?
public class Foo<T> where T : IComparable
{
public void Bar(T value)
{
DoSomething(value);
}
}
No casting needed... and please don't use reserved words to name stuff.
I have read multiple posts but haven't found an appropriate answer for my problem.
But there has to be one. So please be patient if this post really is an duplicate.
I try to initialize a Property of a generic type implementing a generic interface.
My interface looks basically like this:
public interface IMyInterface<TType> : IMyInterface
{
TType Value {get; set;}
// ... and some more ...
}
public interface IMyInterface
{
SetValue(string value);
}
I have multiple Classes implementing IMyInterface without knowing them
at the piece of code, where I need to set the value.
Is it possible to inizialize the "Value"-Property without using the Name of the property?
(Is there a "nice" way to do this?) - It isn't possible to use SetValue< TType >
void SetValue(object obj, string value)
{
// object obj implements IMyInterface<???>
PropertyInfo valueInfo = typeof(obj).GetType().GetProperty("Value")
valueInfo.SetValue(obj, Activator.CreateInstance(valueInfo.PropertyType))
((IMyInterface)obj).SetValue(value);
}
Thanks in advance.
EDIT: - removed -
EDIT 2:
This structure is given:
public Interface IGeneric<TType> : INonGeneric
{
TType Value2 {get;}
}
public Interface INonGeneric
{
object Value1 {get;}
}
using "Value1" from reflection is really easy:
INonGeneric myObject = (INonGeneric)givenObject;
doSomething(myObject.Value1)
if i need to access "Value2" it isn't that easy. As one can see in my first example I had to use the following construct which not seems to be the best way to access "Value2", because the properties name is hardcoded.
PropertyInfo valueInfo = givenObject.GetType().GetProperty("Value2");
object value = (object)valueInfo.GetValue(givenObject);
Is there any better solution?
If i got you right you have and instance that implements IGeneric, and you want to access the property Value2 (which has a generic return type).
The thing is, Generics are for compile time type safety. You cannot cast your object to IGeneric<...> if you don't know the type parameter. So why do you want to use Generics anyway if you don't know the type parameter?
There is a solution for this "problem", it is the same as IEnumerable and IEnumerable< T> uses. it can look something like this:
public interface INonGeneric
{
object Value {get; }
}
public interface IGeneric<T>
{
T Value { get; }
}
public class Magic : INonGeneric, IGeneric<string>
{
object INonGeneric.Value { get { return this.Value; } }
public string Value { get { return "test"; } }
}
You can now use cast the Object to INonGeneric if you don't use the type parameter, or use the Generic implementation if you know the type parameter at compile time.
But if you want to access a property of a generic type (you have no control over) without knowing the type parameter you will not get around either reflection or dynamic.
The dynamic solution can look like this:
dynamic generic = givenObject;
object value2 = generic.Value2;
I'd like to use a certain operation for multiple variable types (both native and objects) so I'm using the generic return type as follows.
private Generic Field<Generic>(String field)
{
if (BagOfJunk.Properties.Contains(field))
return (Generic)BagOfJunk[field];
return default(Generic);
}
This works well (and BagOfJunk is just a property of this from which I'm pulling out Object typed values). Now, during run-time, when a field isn't contained in the bag, I get the default value to be null. Hence, in the code, I need to perform a check as follows.
NumericType protoNumber = Field<NumericType>("beep");
int number = protoNumber != null ? protoNumber.Value : -1;
DateType protoDate = Field<DateType>("boop");
DateTime date = protoDate != null ? protoDate.Value : null;
I'd like to make the code more compact, so I tried to design a method that does the above four lines in one swoop, for a generic type. The result is below but, of course, it doesn't compile, because the type GenericIn isn't specific enough to have a property Value.
private GenericOut Field<GenericIn, GenericOut>(String field)
{
GenericIn input = Field<GenericIn>(field);
if (input != null)
return (GenericOut)input.Value;
return default(GenericOut);
}
How can I ensure the computer that my GenericIn isn't general - by promising that whatever stuff I'll shove into it, it'll always have the property Value in it?
Edit
It should be emphasized that the type of Value needs to be generic ( equivalent to GenericOut). I noticed that I didn't stress that strongly enough. So the interface that can be used need to declare a property of general type like the following.
interface ObjectWithValue { public Generic Value { get; } }
You can use an interface and apply a where constraint on the type to implement that interface, like below:
interface IHasPropertyValue<TValue> {
TValue Value { get; }
}
class MyType {
public TValue Method<T, TValue>(T obj) where T : IHasPropertyValue<TValue> {
return obj.Value;
}
}
EDIT: Modified the code above to make it more specific to the comment asked below.
put that property in an interface (or a class) and use the generic constraint "where":
public interface IMyInterface
{
public object Value { get; set; }
}
public class C<T> where T:IMyInterface
To build upon the answers so far, you need to create an interface that will be implemented by your GenericIn that will both guarantee that it has a property Value and that the property is of type GenericOut.
interface IHasValue<TOut>
{
TOut Value { get; }
}
private TOut Field<TIn, TOut>(string field) where TIn : IHasValue<TOut>
{
var input = Field<TIn>(field);
return input == null ? default(TOut) : input.Value;
}
Is there any way to achieve something like this?
If "Employee" is passed as an argument to a method it should return an object of type Employee.
But without using reflection.
You could use Type.GetType(string) to get the meta data for the type. However, this requires an Assembly Qualified Name of the type unless the type resides in the currently executing assembly or is part of mscorlib.dll.
Then you can use Activator.CreateInstance(Type) to obtain an instance.
var type = Type.GetType(typeName);
var obj = Activator.CreateInstance(type);
At this point, the static type of obj is System.Object. You would need to continue using reflection to get at the properties and methods defined on your actual type, or you could treat the object as dynamic, assuming you don't know at compile time what class to cast the result to (and if you did know, you would skip this entire process).
Edit: With your added constraint of not wanting to use reflection, this changes your options. The code will not be quite as dynamic in regards to what you can support, you will generally need to have an idea ahead of time, but that might be a good thing, depending on what you are trying to accomplish. What you might have is simply a switch statement or a dictionary that has supported types, keying on the name as a string.
public object GetInstanceOf(string typeName)
{
switch (typeName)
{
case "Employee": return new Employee();
case "Manager" : return new Manager();
case "Owner" : return new Owner();
// etc
default:
throw new InvalidOperationException("typeName is not supported");
}
}
Notice with this approach, you know all of your supported types in advance. There are other ways to know the types in advance outside of code (ex: configuration, data), but those would generally get you back into the land of the first part of the answer. Also note that your return type is still limited. It must be a common base type or interface for the classes involved. In my code sample, it's the common base type for all classes and structs, System.Object. For you, this might be more of a factory, with a Worker base class or IWorker interface. Or maybe Employee is the base and your method is constructing specialized children of it. The latter two examples give you compile-time access to the base or interface defined methods and properties.
Yes than you can do with the help of "Reflection"
Try
Employee employee =(Employee)Activator.CreateInstance("Employee");
check #jon skeet answer : How do I create an instance from a string in C#?
Instantiating an Arbitrary Type Without Reflection
I was wrong. There are a lot of ways that you can instantiate a type without true reflection, it would seem. I'll try to compile a list of all that I can find.
Generics
Depending on what you are trying to do, you might be able to do a very cool technique called generics. You can't input an arbitrary name of a type at runtime, so this doesn't necessarily answer your question in full, but if you know the types that you want at compile time, this makes for a great tool. This involves no reflection of any sort, but is entirely compile time. Here's an example:
interface IParsable
{
bool TryParse(string text);
}
class MyInt : IParsable
{
public int Value { get; private set; }
public static MyInt Parse(string text)
{
Parser parser = new Parser();
return parser.Parse<MyInt>(text);
}
}
class MyFloat : IParsable
{
public float Value { get; private set; }
public static MyFloat Parse(string text)
{
Parser parser = new Parser();
return parser.Parse<MyFloat>(text);
}
}
class Parser
{
// The "new()" constraint means that T must have a
// parameterless constructor.
private T Parse<T>(string text)
where T : IParsable, new()
{
// Even though T isn't actually a type, we can use
// it as if it were, for the most part.
T obj = new T();
// Because we had the IParsable constraint, we can
// use the TryParse method.
if (!obj.TryParse(text))
{
throw new Exception("Text could not be parsed.");
}
return obj;
}
}
Dictionary of Lambdas
Credit to Anthony Pegram for his genius on this one (see comments below). Previously I had this using reflection, but he fixed it to work without any reflection whatsoever, thanks to lambda expressions.
static readonly IDictionary<string, Func<object>> Types = new Dictionary<string, Func<object>>()
{
{ "TypeA", () => new TypeA() },
{ "TypeB", () => new TypeB() },
{ "TypeC", () => new TypeC() },
};
// If you're okay with a bit of reflection behind-the-scenes, change "object"
// here to "dynamic", and you won't have to cast down the road.
object void GetInstance(string name)
{
if (Types.ContainsKey(name))
{
return Types[name]();
}
else
{
return null;
}
}
Pre-Instantiated Objects
Yet another option would be to return the same reference each time. This avoids "true" reflection altogether. This idea of reusing instances has some important implications, which could be either good or bad, depending on what you are doing. These implications are very interesting, and can be quite amazing if used properly.
You could, if you wanted, have each type implement a specific interface, and cast to that, instead of returning a raw object.
static readonly IDictionary<string, object> Instances = new Dictionary<string, object>()
{
{ "TypeA", new TypeA() },
{ "TypeB", new TypeB() },
{ "TypeC", new TypeC() },
};
object void GetInstance(string name)
{
if (!Instances.ContainsKey(name))
{
return null;
}
return Instances[name];
}
Instantiating an Arbitrary Type With Reflection
You've got a nice array of answers that will work great if your type has a parameterless constructor. But what if it doesn't?
const string TYPE = "System.String";
Type type = Type.GetType(TYPE);
if (type == null)
{
// Type doesn't exist--at least, not in mscorlib or current assembly,
// or we didn't specify the assembly.
throw new Exception("Could not find type " + TYPE + ".");
}
// Note the Type array. These are the types of the parameters that the
// constructor takes.
ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(char), typeof(int) });
if (ctor == null)
{
// Constructor doesn't exist that takes those parameters.
throw new Exception("Could not find proper constructor in " + TYPE + ".");
}
// Note the object array. These are the actual parameters passed to the
// constructor. They should obviously match the types specified above.
string result = (string)ctor.Invoke(new object[] { 'a', 5 });
You could use Activator.CreateInstance()
Employee employee =(Employee)Activator.CreateInstance("Namespace", "Employee");
Using reflection as #vulkanino says you will end with something like this:
Employee instance = (Employee)Activator.CreateInstance("MyNamespace.Employee, MyAssembly");
Hope this helps you.
Using reflection you can find types in assemblies, whether it be the executing assembly or other loaded ones (you may load them on demand, actually). Without specifying a complete example of how this might work in your scenario, you would then use something along the lines of Activator.CreateInstance to create instances of your found objects.
My question concerns c# and how to access Static members ... Well I don't really know how to explain it (which kind of is bad for a question isn't it?) I will just give you some sample code:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
So thank you guys for your answers (By the way the question is: how would I solve this problem without getting an error). This probably quite an easy question for you!
Edit: Thank you all for your answers!
Though I think the try - catch phrase is the most elegant, I know from my experience with vb that it can really be a bummer. I used it once and it took about 30 minutes to run a program, which later on only took 2 minutes to compute just because I avoided try - catch.
This is why I chose the switch statement as the best answer. It makes the code more complicated but on the other hand I imagine it to be relatively fast and relatively easy to read. (Though I still think there should be a more elegant way ... maybe in the next language I learn)
Though if you have some other suggestion I am still waiting (and willing to participate)
The problem is that TryParse isn't defined on an interface or base class anywhere, so you can't make an assumption that the type passed into your class will have that function. Unless you can contrain T in some way, you'll run into this a lot.
Constraints on Type Parameters
Short answer, you can't.
Long answer, you can cheat:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
I made a static dictionary holding a delegate for the TryParse method of every type I might want to use. I then wrote a generic method to look up the dictionary and pass on the call to the appropriate delegate. Since every delegate has a different type, I just store them as object references and cast them back to the appropriate generic type when I retrieve them. Note that for the sake of a simple example I have omitted error checking, such as to check whether we have an entry in the dictionary for the given type.
To access a member of a specific class or interface you need to use the Where keyword and specify the interface or base class that has the method.
In the above instance TryParse does not come from an interface or base class, so what you are trying to do above is not possible. Best just use Convert.ChangeType and a try/catch statement.
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
One more way to do it, this time some reflection in the mix:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
The next step would be trying to implement
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
With full parameter type matching etc.
This isn't really a solution, but in certain scenarios it could be a good alternative: We can pass an additional delegate to the generic method.
To clarify what I mean, let's use an example. Let's say we have some generic factory method, that should create an instance of T, and we want it to then call another method, for notification or additional initialization.
Consider the following simple class:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
And the following static method:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
So right now we would have to do:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
However, we could change our method to take an additional delegate:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
And now we can change the call to:
var example = CreateAndInit<Example>(Example.PostInitCallback);
Obviously this is only useful in very specific scenarios. But this is the cleanest solution in the sense that we get compile time safety, there is no "hacking" involved, and the code is dead simple.
Do you mean to do something like this:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
Unfortunately you can't check for the TryParse pattern as it is static - which unfortunately means that it isn't particularly well suited to generics.
The only way to do exactly what you're looking for would be to use reflection to check if the method exists for T.
Another option is to ensure that the object you send in is a convertible object by restraining the type to IConvertible (all primitive types implement IConvertible). This would allow you to convert your parameter to the given type very flexibly.
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
You could also do a variation on this by using an 'object' type instead like you had originally.
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
Ok guys: Thanks for all the fish. Now with your answers and my research (especially the article on limiting generic types to primitives) I will present you my solution.
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
You probably cant do it.
First of all if it should be possible you would need a tighter bound on T so the typechecker could be sure that all possible substitutions for T actually had a static method called TryParse.
You may want to read my previous post on limiting generic types to primitives. This may give you some pointers in limiting the type that can be passed to the generic (since TypeParse is obviously only available to a set number of primitives ( string.TryParse obviously being the exception, which doesn't make sense).
Once you have more of a handle on the type, you can then work on trying to parse it. You may need a bit of an ugly switch in there (to call the correct TryParse ) but I think you can achieve the desired functionality.
If you need me to explain any of the above further, then please ask :)
Best code: restrict T to ValueType this way:
class test1<T> where T: struct
A "struct" here means a value type.
String is a class, not a value type.
int, float, Enums are all value types.
btw the compiler does not accept to call static methods or access static members on 'type parameters' like in the following example which will not compile :(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=> Error 1 'T' is a 'type parameter', which is not valid in the given context
SL.
That is not how statics work. You have to think of statics as sort of in a Global class even if they are are spread across a whole bunch of types. My recommendation is to make it a property inside the T instance that can access the necessary static method.
Also T is an actual instance of something, and just like any other instance you are not able to access the statics for that type, through the instantiated value. Here is an example of what to do:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}