Dynamically Casting Objects - c#

Hello everyone I am trying to cast two objects to, both, a specific type based on property reflection information. I want to do this dynamically so I don't need a bunch of switch cases and such for each type that the two objects can be in this class. Overall they will mostly be int or float. At the moment I currently tried using 'var' and 'object' keywords to hold the incoming adjustment value and the properties original value.
// .. snip
/* Get property information. */
PropertyInfo propInfo = classObj.GetType().GetProperty("property-name");
if (propInfo == null)
continue;
/* Prepare object values. */
object orgVal = propInfo.GetValue( classObj, null );
object adjVal = Convert.ChangeType( strAdjust, propInfo.GetType(), new CultureInfo("en-us"));
// .. math on objects here
// ex. orgVal += adjVal;
// .. snip
The incoming adjustment value is in a string but is either in 'int' or 'float' format so it will be easily converted. All of this works fine, it's just the casting to be allowed to adjust the original value with the new adjustment value that is the issue.
I know with .NET 4.0 there is the 'dynamic' keyword that would be able to accomplish something like this, but currently I am stuck using 3.5.
Both objects will use the type from the property information propInfo.GetType().
Any help with this would be greatly appreciated, I'm sure I'm probably overlooking a basic thing here to get this accomplished. Thanks in advance.
-CK
Edit:
Forgot to mention, sorry, this is being developed on a Zune HD, so the framework I have access to is fairly limited to what can/can't be used.

C# 3.5 has a class called TypeConverter
http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx
These provide a mechanism of converting from one type to another based on type information.
System.ComponentModel.TypeConverter GetConverter(System.Type type)
is used to get the converter and
public object TypeConverter.ConvertFrom(object value)
does the conversion. There are built in converters for basic types like int and float, and it is possible to write custom converters for your own types.
Microsoft has a guide to writing them here.
http://msdn.microsoft.com/en-us/library/ayybcxe5.aspx

There's a couple of ways you can do this that I can think of. You can use reflection to get the "op_Addition" method (which is basically "operator +"). But the way I'd do it is via Lambdas:
var orgValueParam = Expression.Parameter(propInfo.PropertyType, "lhs");
var adjValueParam = Expression.Parameter(propInfo.PropertyType, "rhs");
var expr = Expression.Add(orgValueParam, adjValueParam);
var func = Expression.Lambda(expr, orgValueParam, adjValueParam).Compile();
var result = func(orgValue, adjValue);
Note: I haven't actually tested this, so I don't know whether it'll work for sure, but that's where I'd start...

Related

Is it possible to get the type of variable to be assigned via reflection?

I was wondering something like the the following is possible
int foo = GetDefaultValue();
object GetDefaultValue() // Example function, behavior is not the purpose of this question
{
Type t = // Reflection magic
if (t.IsValueType)
return Activator.CreateInstance(t);
return null;
}
I know something similar exists with the CallerMemberNameAttribute attribute, but it doesn't give me what I'm looking for.
I know I can use generics, pass type as parameter etc, but I was curious if it's possible with reflection (just curiosity)
As was mentioned in the comments, default values are already part of the language:
int myInteger = default;
You don't need anything extra for this.
I know I can use generics, pass type as parameter etc, but I was curious if it's possible with reflection (just curiosity)
Reflection on what?
You're not passing anything. Reflection either involves instantiation based on a dynamically passed type, or typing/accessing properties based on a dynamically passed object.
But you're not providing a type or an instance, so there is nothing to reflect on here.

Can C# return a type in a method?

can i have something like:
AMess.Foo = MessyData.GetData<MessyData.GetType(key)>(key);
?
my problem is similar to my example. I have a data source is dynamically typed, so i have to do something to determine the data type. but it's a pain in the ass to put type check everywhere. so i think maybe i could have some code just to tell me what type it is. can i do this?
or maybe better solution?
please not worry about AMess.Foo, it eats everything.
No, it can't. You'll have to use Reflection instead. I don't have Visual Studio installed on my machine at the moment so I can't test the syntax at the moment, but this should be close:
var type = MessyData.GetType(key);
var castMethod = MessyData.GetType().GetMethod("GetData").MakeGenericMethod(type);
AMess.Foo = castMethod.Invoke(MessyData, new[] { key });
No. Generic type arguments must be resolved at compile-time.
If you use:
MessyData.GetData<SomeType>(key);
then SomeType needs to be the name of a specific class (or interface, struct, etc.). It can never be an expression like in your question.
If you let the type be inferred, as in:
MessyData.GetData(key); // infer type arg
then the type used in the call is the compile-time type of the key variable, not the run-time type. These types can differ.
If you really want dynamic typing, you can have GetData take in a parameter of type dynamic (the method will be non-generic). But what is the problem you are trying to solve?

Dynamically setting type or result from invoked generic method?

My apologies if the question is somewhat unclear; I'm not entirely certain how to phrase this.
My issue is this. I have two classes, Manager<T> and Result<T>. Within Manager<T>, I have a whole raft of retrieval functions. Ordinarily, I would call Manager<T> and set its type like so:
Manager<SpecialDataType> mgr = new Manager<SpecialDataType>;
After which I set up my Result type, and fill it with my function from Manager, where 1 is a parameter for the GetItem function shown. I can then access things in my item:
Result<SpecialDataType> item = new Result<SpecialDataType>;
item = mgr.GetItem(1);
string x = item.Teaser;
OK. So now, what I'm trying to do is set the <SpecificDataType> to be filled in at run time. I think I've got half of the solution already, using generic types, like so:
Type generalType= Type.GetType("SpecificDataType");
Type managerType= typeof(Manager<>).MakeGenericType(generalType);
var managerInstance= Activator.CreateInstance(managerType);
object[] args = {1};
MethodInfo getItemMethod = managerInstance.GetMethod("GetItem");
But here's where I get stuck. There are specific properties that my Result class has that I need to be able to access. They are, or course, set by the data type I'm casting into. When I do an Invoke, like so:
var item = getItemMethod.Invoke(managerInstance, args);
I'm not getting any of my properties that I know are part of item. That makes sense, I suppose, because we don't know what item is. So, we tried this:
Type dataType = typeof(SmartFormData<>).MakeGenericType(sfType);
var item = Activator.CreateInstance(dataType);
item = getItemMethod.Invoke(managerInstance, args);
And got the same result. I can't seem to get to item.Teaser.
I'm not a c# coder natively (as though that's not apparent already from this overly complicated question I'm asking), so I'm not incredibly familiar with reflection and generic types. Can anyone point me in the right direction for how to solve this problem, or how to approach it from a different angle? The only caveat is that I cannot modify the Manager<T> and Result<T> functions; I have to use what I'm given there.
Thanks in advance for any help you can offer.
As Dark Falcon correctly notes in his comment you will have to use reflection to get the members of your item.
Or, if you are in .NET 4 or above, you can use the dynamic keyword to greatly simplify things:
Type generalType= Type.GetType("SpecificDataType");
Type managerType= typeof(Manager<>).MakeGenericType(generalType);
dynamic managerInstance = Activator.CreateInstance(managerType);
var item = managerInstance.GetItem(1);
string x = item.Teaser;
You need to cast the invocation result to the type you're expecting
var item = (Result<SpecificDataType>)getItemMethod.Invoke(managerInstance, args);

C# implicit conversions

I'm currently working on an application where I need to load data from an SQL database and then assign the retrieved values into the properties of an object. I'm doing this by using reflection since the property names and column names are the same. However, many of the properties are using a custom struct type that is basically a currency wrapper for the decimal type. I have defined an implicit conversion in my struct:
public static implicit operator Currency(decimal d)
{
return new Currency(d);
}
This works fine when I use it in code. However, when I have this:
foreach (PropertyInfo p in props)
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
It throws an ArgumentException stating that it cannot convert from System.Decimal to Currency. I'm confused since it works fine in any other circumstance.
Unfortunately, these user-defined conversion operators are not used by the runtime; they are only used by the compiler at compile time. So if you take a strongly-typed decimal and assign it to a strongly-typed Currency, the compiler will insert a call to your conversion operator and everybody's happy. However, when you call SetValue as you're doing here, the runtime expects you to give it a value of the appropriate type; the runtime has no idea that this conversion operator exists, and won't ever call it.
I think you need to first unbox the value in table.Rows[0][p.Name] as a decimal.
In other words:
foreach (PropertyInfo p in props)
{
if (p.PropertyType == typeof(Currency))
{
Currency c = (decimal)table.Rows[0][p.Name];
p.SetValue(this, c, null);
}
else
{
p.SetValue(this, table.Rows[0][p.Name], null);
}
}
This is an issue I've seen once or twice before, so I actually decided to write a blog post about it. Anybody looking for a little more explanation, feel free to give it a read.
I assume that table is of type DataTable in your code, so the first indexer returns a DataRow, and the second one returns an object. Then PropertyInfo.SetValue also takes an object as the second argument. At no place in this code a cast happens in the code, which is why the overloaded conversion operator is not applied.
Generally speaking, it is only applied when static types are known (forgetting about dynamic in C# 4.0 for the moment). It is not applied when boxing and unboxing things. In this case, the indexer on DataRow boxes the value, and PropertyInfo.SetValue tries to unbox it to a different type - and fails.
Whilst I am not answering your problem, I think in this kind of situation it would be more appropriate to use a ORM Framework like the Entity Framework or NHibernate which will map your tables into your domain objects and handle all the conversions for you. Using something like reflection to figure out what fields to fill in a domain object is a slow way to do it.

When should the var type be used in c#? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What’s the point of the var keyword?
What is the var type and should it be used in c#? When should it be used?
Can you specify the var type for the parameters to a method?
var is not a type. It is a convinient short hand notation that saves you a lot of typing. The following two declarations are equivalent:
Dictionary<string,List<int>> dic = new Dictionary<string,List<int>>();
and
var dic = new Dictionary<string,List<int>>();
As you can see, this saves typing and are easier to read. And if you descide to change the data type, you only have to change the right hand part.
But where I really like it most is in foreach loops:
foreach ( var item in someList )
Here item automatically takes the correct type, depending on the type of someList and it enables you to change the type of someList without haveing to change the declaration of item.
In short: var is GREAT and should be used.
EDIT: No, you can not specify var as a parameter to a function. The closest you can get to that is generics, I guess. And I also completely forgot to mention anonymous types. With those you have to use var.
It is part of the language, so yes, it should be used. It is not a type, however, but signifies a placeholder for the actual type determined by the compiler.
When should you use it? This has been asked before, many times:
Use of var keyword in C#
https://stackoverflow.com/questions/633474/c-do-you-use-var
var is not a type, it's an instruction to the compiler to let it figure out the correct type to use.
This means there is no difference at all to the output of the following two lines:
var s = "Test";
string s = "Test";
As for when to use it, you'll have to come up with your own rules. There is very few things you can do with var that you cannot do with a specific type name, but there is one thing: anonymous types.
You can do:
var x = new { A = 10 };
but you cannot come up with a strong type for that, since it has no type known at compile-time, instead the compiler will create the type during compilation, and then var will use that type.
That's what var was created to support, that it can also be used without anonymous types is a bonus, but you'll have to make up your own rules for when to use it in those cases.
Personally I only use it when the type is easily read from the source code, so I would use it for:
var dict = new Dictionary<int, string>();
var stream = new FileStream(...);
but not for:
var dict = GetDataStructure();
var stream = OpenFileForReading();
We tend to use it when interacting with all of our home grown libraries.
This is because we often change things as we are developing the libraries and quite often changing the type name or return type won't actually break the things which are using it.
We also tend to use it most of the time with the .NET framework as well.
However, we have put in an outright ban on using it with native types like int, string, bool etc. because it is not always clear what type the variable is in those cases.
Well, as mentioned earlier var is a short notation for a type name of any variable. As for me, I find, that var is overused by many developers and I think var makes code less readable sometimes. But one case where u should use it definitely is anonimous type variables.
Just to add to the other commentary, I suggest using var only when you can infer the type just by reading the code
var x = new Widget(); //ok
var y = Customer.Create(); // ok
var z = DoSomething(); //not ok
Some of the answers introduce Anonymous Types.
The var keyword on MSDN.
Know that var is not a type but a placeholder and can only be used within methods or properties (local variable definition). You can't use it in local member definition (private members of a class), neither can you when defining a method that should return whatever type, as generics, where you can use whatever name, except var (or any other reserved keyword) like so:
public IList<var> GetItems() { // Here the compiler will complain about the context of using `var` keyword within a local variable definition only.
}
public IList<T> GetItems() { // Here, we're talking about generics.
}
So, here are the principal rules to follow using the var keyword:
Local variable definition only;
Use var with anonymous types (Linq query, for instance);
Not to be confused with generic types;

Categories