I am building a helper function to map properties of an object to an object, which knows to which UI component the property is bound and how to convert their values back and forth.
Now I need the map itself, to map property names (of type String) to their ModelFieldItems, which contain a generic converter (eg StringToBoolConverter). But due to the lack of the <?> Operator, I'm used to from java, I can't simply write private Dictionary<String, ModelFieldItem> items = new Dictionary<String, ModelFieldItem<?,?>>();
where ModelFieldItem contains the type Information and the converter itself.
As a result I need to add specific Types if I want to add a ModelFieldItem to the map, but they differ in type.
I already tried to use dynamic or object as type parameters, but sooner or later I reach a point, where it does not work.
Using the trick from C# - Multiple generic types in one list I got the compiler happy, but I needed a typecast to access my converter logic, which led me to the following condition
if (item is ModelFieldItem<dynamic, dynamic>)
{
ModelFieldItem<dynamic, dynamic> dynamicItem = (ModelFieldItem<dynamic, dynamic>)item;
Which always resolves to false.
EDIT
The Method, which starts the conversion, does not know, which types to convert, which is desired. We are using a loop to iterate over the properties and start their corresponding converters. So casting at the point of conversion can not be done with the distinct types, because we can not know them.
Our converters are as easy as they can be, inheriting from the following abstract class
public abstract class TypedConverter<A, B>
{
public abstract B convertFrom(A value);
public abstract A convertTo(B value);
}
As mentioned before, I'm from a java background, so what I want to achieve looks roughly like the following in Java
private Map<String, ModelFieldItem<?,?>> converters = new HashMap<>();
and I would use it roughly like
converters.put("key", new Converter<String, Boolean>());
How can I achieve this in C#?
Usually when you encounter this type of problem, you have to use an abstraction of your class that doesn't require the generic types.
If your ModelFieldItem implement an interface without generic parameters, you can use it.
var _dict = new Dictionary<String, IModelFieldItem>()
{
new Converter<string, bool>() // If it's implement IModelFieldItem
};
(YouWillHaveToCastUnlessYouUseDynamicType)_dict[key].Convert("true");
Otherwise, another way would be to replace the ModelFieldItem from Dictionary<String, ModelFieldItem> by object or dynamic, then you can cast it when accessing to the value from your dictionary.
var _dict = new Dictionary<String, object>()
{
new Converter<string, bool>()
};
// You can avoid the cast too by using dynamic
// But it will cost you some perf
((Converter<string, bool>)_dict[key]).Convert("true");
if you know the type that you want.
You can do something like that:
var _dict = new Dictionary<String, object>()
{
new Converter<string, bool>()
};
public void Convert<TToConvert, TConverted>(string key, TToConvert valueToConvert, out TConverted valueConverted)
{
valueConverted = (T)_dict[key].Convert(valueToConvert);
}
bool value;
Convert("Key", "true", out value);
Here an other example of what you could do:
public static void Convert<TToConvert, TConverted>(TToConvert valueToConvert, out TConverted valueConverted)
{
// You should put the dictionary outside of the method
// To avoid to instance it, each time you call this method
var dict = new Dictionary<Type, Func<object, object>>()
{
{ typeof(Tuple<string, int>), x => int.Parse((string)x) },
{ typeof(Tuple<string, bool>), x => bool.Parse((string)x) }
};
valueConverted = (TConverted)dict[typeof(Tuple<TToConvert, TConverted>)](valueToConvert);
}
static void Main(string[] args)
{
bool boolTest;
Convert("false", out boolTest);
Console.WriteLine(boolTest);
int intTest;
Convert("42", out intTest);
Console.WriteLine(intTest);
Console.ReadKey();
}
Obvisouly, you should try if you can convert your type first and also if the conversion succeed. Finally make Convert return an boolean to know if it succeed or not.
But at least as you can see, there is no more string key required to make the conversion and it might interests you.
You also have to be sure that your variables have the right type when you pass them to the method, otherwise you will search for the wrong key.
Reflection solution:
With the above method you can do something like that:
static void Main(string[] args)
{
object[] parameters = new object[] { "false", true };
typeof(Program).GetMethod("Convert")
// Be sure that the types will create a valid key
.MakeGenericMethod(new Type[] { parameters[0].GetType(), parameters[1].GetType() })
// Change null to your instance
// if you are not calling a static method
.Invoke(null, parameters);
// parameters[1] is an out parameter
// then you can get its value like that
Console.WriteLine(parameters[1]);
Console.ReadKey();
}
With properties, that should look like this:
object[] parameters = new object[]
{
propertyToRead.GetValue(objectToRead),
propertyToSet.GetValue(objectToSet)
};
typeof(MapperObject).GetMethod("Convert")
.MakeGenericMethod(new Type[]
{
propertyToRead.PropertyType,
propertyToSet.PropertyType
})
.Invoke(mapperInstance, parameters);
propertyToSet.SetValue(objectToSet, parameters[1]);
You may need to adjust it a bit, since I didn't try to compile it
I could give another solution, but I neither know what is your inheritance architecture nor how your Converter works.
Related
I'm not quite sure the correct way of asking this question, so I'm just going to go for it.
I am looking for the cleanest way of passing in "parameter sets" into a Method. For instance:
Dictionary<string, string> Parameters = new Dictionary<string, string>();
Parameters.Add("UserID", "12");
Parameters.Add("SiteID", "43");
CreateLog("Hello World!", Parameters);
public void CreateLog(string Message, Dictionary<string, string> Parameters)
{
...
}
However, I would like to do this in a much cleaner way and I'm sure there is some method of doing it that I can't think of. I could make a custom object that takes a string and an object, for instance:
public void CreateLog(string Message, params LogParameter[] Parameters)
{
...
}
Then I could create a new Log Parameter for each Parameter and pass it in, but I would like to be a bit more concise than that and avoid having to create all those new objects for something that (I think) should be simpler.
One possible solution is to do something like this:
CreateLog("Hello World!", new { UserID = 12, SiteID = 43 });
public void CreateLog(string Message, object Parameters)
{
...
}
This is similar to how C# ASP.NET creates URL variables/how DevExpress creates callbacks for their controls. But how do they get the values out of the object in the method?
Any thoughts?
Three options as I see it:
Use a dictionary as you've already suggested.
Create a class that functions as a DTO and pass that:
public class LogParameters
{
public int UserId { get; set; }
public int SiteId { get; set; }
}
public void CreateLog(string message, LogParameters parameters)
Use an anonymous object, an approach you've also suggested. In your method, you'll have to rely on reflection to transform the object into something you can actually utilize.
Microsoft provides a way to do this via HtmlHelper.AnonymousObjectToHtmlAttributes, but so you don't need a dependency on the System.Web.Mvc namespace, the source for that method is as follows:
public static IDictionary<string, object> AnonymousObjectToHtmlAttributes(object htmlAttributes)
{
Dictionary<string, object> result;
var valuesAsDictionary = htmlAttributes as IDictionary<string, object>;
if (valuesAsDictionary != null)
{
result = new Dictionary<string, object>(valuesAsDictionary, StringComparer.OrdinalIgnoreCase);
}
else
{
result = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
if (htmlAttributes != null)
{
foreach (var prop in htmlAttributes.GetType().GetRuntimeProperties())
{
var value = prop.GetValue(htmlAttributes);
result.Add(prop.Name, value);
}
}
}
return result;
}
That should give you the inspiration you need to adapt it for your own code.
Personally, I generally go with approach 1 or 2 in these scenarios. The syntactic sugar of using an anonymous object is tempting, but if your method depends on the proper params being provided, it can be a crap shoot. Honestly, the dictionary approach suffers in this way as well, but at least there, you're not dealing with reflection.
Technically speaking, methods should be self-documenting, which means you should be passing in either individual named params or a class instance. That way, you have the assurance that what you expect to be available to your method is there, and the end-user of the method can see at a glance what's required to satisfy it. Neither a dictionary nor an anonymous object gives you either of these, and if you notice, the only times Microsoft uses anonymous objects as a param, the contents are completely optional, such as htmlAttributes in a helper. If certain keys don't exist, then it's no big deal, since it's all optional anyways.
Here's the catch, how you can use reflection to get properties out of a Anonymous type passed as object to a method.
public void CreateLog(object parameters)
{
foreach(var property in parameters.GetType().GetProperties())
{
WriteLog(string.Format("{0} - {1}",property.Name, property.GetValue(parameters)));
}
}
Usage:
CreateLog(new {SiteID = 1, UserId = 2});
I am trying to remove duplicate code for collections of System.Func with variable numbers of arguments. (This is used to allow code to "hook" into the logic of other components.)
So I am trying to remove several almost identical methods and use generic methods instead.
To make it work I wrapped them in a HookContainer class and made it implement a common interface.
public interface IHookContainer
{
void Add<TFunc> (string filterName, int priority, KeyValuePair<string, TFunc> action);
}
public class HookContainer<T>:IHookContainer
{
Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>> ();
public void Add<T> (string filterName, int priority, KeyValuePair<string, T> action)
{
// Add an item to the Dictionary
}
}
This allows me to put them all in a single Dictionary which I can access with the Type
Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer> (){
{
typeof(HookContainer<System.Func<object,object>>),new HookContainer<System.Func<object,object>>()
},
// More dictionary entries like this (with more parameters)
};
public string AddFilter<T> (string filterName, T action, string filterTag = null, int priority=0)
{
KeyValuePair<string, T> data = new KeyValuePair<string, T> (filterTag, action);
if (containers.ContainsKey (typeof(T))) {
IHookContainer container = containers [typeof(T)];
container.Add<T> (filterName, dictPriority, data);
}
return filterTag;
}
Now I get a compile error saying:
cannot convert `System.Collections.Generic.KeyValuePair<string,T>'
expression to type `System.Collections.Generic.KeyValuePair<string,T>'
So it's apparently lacking some information that I take for granted. Or I am thinking wrong. Or both.
Why can't it convert a type to ...itself??
I apparently cannot use the same Type parameter from the Generic class for the generic method if the implemented interface. Sadly, the type cannot be inferred either. Is there any way to make this work?
There is also a warning that the type paramater name is the same as the outer type paramemter. Can I tell the compiler that this is completely intended?
Thanks for any help. I am using C# 4.0
Update:
I can get the code to work by declaring the HookContainer with a second Type parameter and using this for passing it into the Add method.
So it looks like this now:
public class HookContainer<T,U>:IHookContainer
{
Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>> ();
public void Add<U> (string filterName, int priority, KeyValuePair<string, T> action)
{
// Add an item to the Dictionary
}
}
This, of course requires me to redundantly pass the Type of the Container twice when declaring the Dictionary:
Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer> (){
{
typeof(HookContainer<System.Func<object,object>,System.Func<object,object>>),new HookContainer<System.Func<object,object>,System.Func<object,object>>()
}
};
So while this might work, it looks and feels ridiculous. Is there any way to just (re)use a single Type parameter?
Update
I misread your question. The way you implement this, is not what you want I think. The declaration in your interface is different from what you want in your implementation.
In your interface declaration you specify that implementations of this interface should have a generic function (which can be called with all kinds of types). In your implementation you want to limit this just to the type that you specify in the class.
The class implementation will be for one specific type.
I.e. the IHookContainer interface specifies you can call the Add function with int,string, etc. Whereas in HookContainer<string> you can only call Add with a string argument.
A more suitable implementation to what you want, but you can not store that in the Dictionary is:
public interface IHookContainer<T>
{
Add(string filterName, int priority, KeyValuePair<string, T> action);
}
What a solution can be (what I might do) is to change the Dictionary to a List and create a function that retrieves the correct IHookContainer<T>. Or keep your dictionary when the number of items is large and address the correct one by key.
private List<object> containers = new List<object>();
private IHookContainer<T> GetCorrectHookContainer<T>()
{
// might need to add when not available?
return containers.OfType<IHookContainer<T>>().FirstOrDefault();
}
your AddFilter function will be something like this (pseudo-code)
public void AddFilter<T>(...)
{
GetCorrectHookContainer<T>().Add(...);
}
Old:
Because you specified the type argument (again) in your function, the T of the class is different from the T in the function. The T argument in your generic function 'hides' the T of the class. You can just use it. You do not have to specify this in your function. Your implementation can be:
public void Add(string filterName, int priority, KeyValuePair<string, T> action)
{
// Add an item to the Dictionary
}
example use:
var x = new HookContainer<int>();
x.Add("test", 1, new KeyValuePair<string,int>("test", 4));
It seems that the problem is TFrom from Add and T from HookContainer are two different generic types.
I don't know if it's possible, but I would use the C's main signature (int argc, char[] argv) instead of the Func functions:
System.Func<int, object[], object>
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.
I would like to implement a method with the following signature
dynamic Cast(object obj, Type castTo);
Anyone know how to do that? obj definitely implements castTo but needs to be cast properly in order to have some of my app's runtime binding stuff work out.
Edit: If some of the answers don't make sense it's because I initially accidentally typed dynamic Cast(dynamic obj, Type castTo); - I mean the input should be object or some other guaranteed base class
I think you're confusing the issues of casting and converting here.
Casting: The act of changing the type of a reference which points to an object. Either moving up or down the object hierarchy or to an implemented interface
Converting: Creating a new object from the original source object of a different type and accessing it through a reference to that type.
It's often hard to know the difference between the 2 in C# because both of them use the same C# operator: the cast.
In this situation you are almost certainly not looking for a cast operation. Casting a dynamic to another dynamic is essentially an identity conversion. It provides no value because you're just getting a dynamic reference back to the same underlying object. The resulting lookup would be no different.
Instead what you appear to want in this scenario is a conversion. That is morphing the underlying object to a different type and accessing the resulting object in a dynamic fashion. The best API for this is Convert.ChangeType.
public static dynamic Convert(dynamic source, Type dest) {
return Convert.ChangeType(source, dest);
}
EDIT
The updated question has the following line:
obj definitely implements castTo
If this is the case then the Cast method doesn't need to exist. The source object can simply be assigned to a dynamic reference.
dynamic d = source;
It sounds like what you're trying to accomplish is to see a particular interface or type in the hierarchy of source through a dynamic reference. That is simply not possible. The resulting dynamic reference will see the implementation object directly. It doesn't look through any particular type in the hierarchy of source. So the idea of casting to a different type in the hierarchy and then back to dynamic is exactly identical to just assigning to dynamic in the first place. It will still point to the same underlying object.
This should work:
public static dynamic Cast(dynamic obj, Type castTo)
{
return Convert.ChangeType(obj, castTo);
}
Edit
I've written the following test code:
var x = "123";
var y = Cast(x, typeof(int));
var z = y + 7;
var w = Cast(z, typeof(string)); // w == "130"
It does resemble the kind of "typecasting" one finds in languages like PHP, JavaScript or Python (because it also converts the value to the desired type). I don't know if that's a good thing, but it certainly works... :-)
I realize this has been answered, but I used a different approach and thought it might be worth sharing. Also, I feel like my approach might produce unwanted overhead. However, I'm not able to observer or calculate anything happening that is that bad under the loads we observe. I was looking for any useful feedback on this approach.
The problem with working with dynamics is that you can't attach any functions to the dynamic object directly. You have to use something that can figure out the assignments that you don't want to figure out every time.
When planning this simple solution, I looked at what the valid intermediaries are when attempting to retype similar objects. I found that a binary array, string (xml, json) or hard coding a conversion (IConvertable) were the usual approaches. I don't want to get into binary conversions due to a code maintainability factor and laziness.
My theory was that Newtonsoft could do this by using a string intermediary.
As a downside, I am fairly certain that when converting the string to an object, that it would use reflection by searching the current assembly for an object with matching properties, create the type, then instantiate the properties, which would require more reflection. If true, all of this can be considered avoidable overhead.
C#:
//This lives in a helper class
public static ConvertDynamic<T>(dynamic data)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(data));
}
//Same helper, but in an extension class (public static class),
//but could be in a base class also.
public static ToModelList<T>(this List<dynamic> list)
{
List<T> retList = new List<T>();
foreach(dynamic d in list)
{
retList.Add(ConvertDynamic<T>(d));
}
}
With that said, this fits another utility I've put together that lets me make any object into a dynamic. I know I had to use reflection to do that correctly:
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
return expando as ExpandoObject;
}
I had to offer that function. An arbitrary object assigned to a dynamic typed variable cannot be converted to an IDictionary, and will break the ConvertDynamic function. For this function chain to be used it has to be provided a dynamic of System.Dynamic.ExpandoObject, or IDictionary<string, object>.
Best I got so far:
dynamic DynamicCast(object entity, Type to)
{
var openCast = this.GetType().GetMethod("Cast", BindingFlags.Static | BindingFlags.NonPublic);
var closeCast = openCast.MakeGenericMethod(to);
return closeCast.Invoke(entity, new[] { entity });
}
static T Cast<T>(object entity) where T : class
{
return entity as T;
}
The opensource framework Dynamitey has a static method that does late binding using DLR including cast conversion among others.
dynamic Cast(object obj, Type castTo){
return Dynamic.InvokeConvert(obj, castTo, explict:true);
}
The advantage of this over a Cast<T> called using reflection, is that this will also work for any IDynamicMetaObjectProvider that has dynamic conversion operators, ie. TryConvert on DynamicObject.
Try a generic:
public static T CastTo<T>(this dynamic obj, bool safeCast) where T:class
{
try
{
return (T)obj;
}
catch
{
if(safeCast) return null;
else throw;
}
}
This is in extension method format, so its usage would be as if it were a member of dynamic objects:
dynamic myDynamic = new Something();
var typedObject = myDynamic.CastTo<Something>(false);
EDIT: Grr, didn't see that. Yes, you could reflectively close the generic, and it wouldn't be hard to hide in a non-generic extension method:
public static dynamic DynamicCastTo(this dynamic obj, Type castTo, bool safeCast)
{
MethodInfo castMethod = this.GetType().GetMethod("CastTo").MakeGenericMethod(castTo);
return castMethod.Invoke(null, new object[] { obj, safeCast });
}
I'm just not sure what you'd get out of this. Basically you're taking a dynamic, forcing a cast to a reflected type, then stuffing it back in a dynamic. Maybe you're right, I shouldn't ask. But, this'll probably do what you want. Basically when you go into dynamic-land, you lose the need to perform most casting operations as you can discover what an object is and does through reflective methods or trial and error, so there aren't many elegant ways to do this.
Slight modification on #JRodd version to support objects coming from Json (JObject)
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
//Get the type of object
Type t = value.GetType();
//If is Dynamic Expando object
if (t.Equals(typeof(ExpandoObject)))
{
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
}
//If coming from Json object
else if (t.Equals(typeof(JObject)))
{
foreach (JProperty property in (JToken)value)
expando.Add(property.Name, property.Value);
}
else //Try converting a regular object
{
string str = JsonConvert.SerializeObject(value);
ExpandoObject obj = JsonConvert.DeserializeObject<ExpandoObject>(str);
return obj;
}
return expando as ExpandoObject;
}
You can use the expression pipeline to achieve this:
public static Func<object, object> Caster(Type type)
{
var inputObject = Expression.Parameter(typeof(object));
return Expression.Lambda<Func<object,object>>(Expression.Convert(inputObject, type), inputPara).Compile();
}
which you can invoke like:
object objAsDesiredType = Caster(desiredType)(obj);
Drawbacks: The compilation of this lambda is slower than nearly all other methods mentioned already
Advantages: You can cache the lambda, then this should be actually the fastest method, it is identical to handwritten code at compile time
Alternatively:
public static T Cast<T>(this dynamic obj) where T:class
{
return obj as T;
}
I'm creating a Settings object in my app, used for storing user-defined settings and whatnot. I plan on using various datatypes for my setting fields (ints, strings, enums, anything Serializable, really).
I'd also like, if possible, a type-safe way to set any of the settings. My proposed method would be doing something like this:
Tuple<string, Type> SettingName = new Tuple<string, Type>("NumberOfFoos",
typeof(**TYPE**));
public void Set(Tuple<string, Type> key, **TYPE** value) { /* Stuff */ }
The Tuple would effectively be the "setting" that the user would push a value to, and would consist of the key for that setting as well as the type of that setting. What I'm wondering is if there's any way to have the compiler enforce that, in the Set() method, the type of value is of the same type as the type object saved in the tuple passed to Set()? Is the way I proposed even possible? Thanks!
EDIT: I thought of some more things I should clarify.
1) This is intended to be a static class, so I won't be able to serialize the whole class, only members in it. Therefore, I'd really like to not have to deal with a serialization for each field. I was planning on storing all the setting values in a Dictionary<string, **TYPE**> and serializing that.
2) The Tuple definitions are meant to be constant and static. I'm really treating them as more of a typedef-type thing (I really should make my own SettingKey struct), which the user passes to Set to indicate what field they are changing. The Type parameter is meant to enforce the the value parameter is of the specified type.
Something like
public void Set<T>(Tuple<string,T> key, T value) { /* stuff */ }
might do it
It's better to get rid of the tuple, and use a generic method:
public void Set<T>(string key, T value);
That way, you can specify the type at compile-time
Set<string>("MyStringKey", "foo");
Set<int>("MyIntKey", 1);
or the compiler can infer it for you:
Set("MyStringKey", "foo");
Set("MyIntKey", 1);
and in Set, you can use typeof(T) to get the Type object you would have passed in.
Why not simply add strongly typed properties to your settings object? e.g. public int NumberOfFoos {get {} set {...}} and in the getter and setter call your common serialization and deserialization code.
If you do this your settings object isn't exposing how it works internally and you have full intellisense support on it.
Well, if you did something like Set<T>(Tuple<string, T>, T value), you'd get what you're after for setting. And I think the compiler could infer the T in Set<T>() at usage, so you would have to write it.
But your Get<T>(), you'd have to specify the type you expected to get back.
public class Foo
{
Tuple<string, Type> SettingName = new Tuple<string, Type>("NumberOfFoos",
typeof(**TYPE**));
public void Set(Tuple<string, Type> key, object value)
{
if(value.GetType() != SettingsName.Value)
throw new ArgumentException("value");
}
}
You would be better of using generics like in the other answers though.
I don't think you need to deal with Types at all. Would something like this be good enough?
class Settings {
public static int Foo {
get { return (int)_map["Foo"]; }
set { _map["Foo"] = value; }
}
public static string Bar {
get { return (string)_map["Foo"]; }
set { _map["Foo"] = value; }
}
// ...
private static Dictionary<string, object> _map =
new Dictionary<string, object>();
}
You'd then serialize the dictionary. You could even use some code-generation to create this class.