An object has some properties , now at runtime -- when a condition is met .. I want to add new properties to this object .
"DynamicObject" cant be ustilised since i wont be knowing the property Names beforehand .
I came acroos PropertyBuilder http://msdn.microsoft.com/en-us/library/system.reflection.emit.propertybuilder.aspx
But i cant find help regarding how to use the propertBuilder for adding properties to an existing object of a defined-existing class.
You cannot add real (reflection) properties to an object or type at runtime.
If the context here is data-binding, then you can all artificial properties, by implementing one or more of ICustomTypeDescriptor, TypeDescriptionProvider, TypeConverter, ITypedList - and providing your own PropertyDescriptors for the extra properties.
ICustomTypeDescriptor is per-object and tied to that object
TypeDescriptionProvider is per-object or per-type, and is separate to the object
TypeConverter is per-type and is used in particular by PropertyGrid
ITypedList is used by a list (IList) to describe the properties of the child objects
Example:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
FooConverter.AddProperty("Time", typeof(DateTime));
FooConverter.AddProperty("Age", typeof(int));
using (var grid = new PropertyGrid { Dock = DockStyle.Fill, SelectedObject = new Foo() })
using (var form = new Form { Controls = { grid } })
{
Application.Run(form);
}
}
}
class FooConverter : ExpandableObjectConverter
{
private static readonly List<Tuple<string, Type>> customProps = new List<Tuple<string, Type>>();
public static void AddProperty(string name, Type type)
{
lock (customProps) customProps.Add(Tuple.Create(name, type));
}
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, System.Attribute[] attributes)
{
var orig = base.GetProperties(context, value, attributes);
lock(customProps)
{
if(customProps.Count == 0) return orig;
PropertyDescriptor[] props = new PropertyDescriptor[orig.Count + customProps.Count];
orig.CopyTo(props, 0);
int i = orig.Count;
foreach (var prop in customProps)
{
props[i++] = new SimpleDescriptor(prop.Item1, prop.Item2);
}
return new PropertyDescriptorCollection(props);
}
}
class SimpleDescriptor : PropertyDescriptor
{
private readonly Type type;
public SimpleDescriptor(string name, Type type)
: base(name, new Attribute[0])
{
this.type = type;
}
public override Type PropertyType { get { return type;} }
public override bool SupportsChangeEvents { get { return false; } }
public override void ResetValue(object component) { SetValue(component, null); }
public override bool CanResetValue(object component) { return true; }
public override bool ShouldSerializeValue(object component) { return GetValue(component) != null; }
public override bool IsReadOnly { get { return false; } }
public override Type ComponentType { get { return typeof(Foo); } }
public override object GetValue(object component) { return ((Foo)component).GetExtraValue(Name); }
public override void SetValue(object component, object value) { ((Foo)component).SetExtraValue(Name, value); }
public override string Category { get { return "Extra values"; } }
}
}
[TypeConverter(typeof(FooConverter))]
public class Foo
{
Dictionary<string, object> extraValues;
internal object GetExtraValue(string name)
{
object value;
if (extraValues == null || !extraValues.TryGetValue(name, out value)) value = null;
return value;
}
internal void SetExtraValue(string name, object value)
{
if (extraValues == null && value != null) extraValues = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
if (value == null) extraValues.Remove(name);
else extraValues[name] = value;
}
public int Id { get; set; }
public string Name { get; set; }
}
Check this Address
https://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes(v=vs.110).aspx
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
class EmitWriteLineDemo {
public static Type CreateDynamicType() {
Type[] ctorParams = new Type[] {typeof(int),
typeof(int)};
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder pointModule = myAsmBuilder.DefineDynamicModule("PointModule",
"Point.dll");
TypeBuilder pointTypeBld = pointModule.DefineType("Point",
TypeAttributes.Public);
FieldBuilder xField = pointTypeBld.DefineField("x", typeof(int),
FieldAttributes.Public);
FieldBuilder yField = pointTypeBld.DefineField("y", typeof(int),
FieldAttributes.Public);
Type objType = Type.GetType("System.Object");
ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
ConstructorBuilder pointCtor = pointTypeBld.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
ctorParams);
ILGenerator ctorIL = pointCtor.GetILGenerator();
// First, you build the constructor.
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Call, objCtor);
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_1);
ctorIL.Emit(OpCodes.Stfld, xField);
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_2);
ctorIL.Emit(OpCodes.Stfld, yField);
ctorIL.Emit(OpCodes.Ret);
// Now, you'll build a method to output some information on the
// inside your dynamic class. This method will have the following
// definition in C#:
// public void WritePoint()
MethodBuilder writeStrMthd = pointTypeBld.DefineMethod(
"WritePoint",
MethodAttributes.Public,
typeof(void),
null);
ILGenerator writeStrIL = writeStrMthd.GetILGenerator();
// The below ILGenerator created demonstrates a few ways to create
// string output through STDIN.
// ILGenerator.EmitWriteLine(string) will generate a ldstr and a
// call to WriteLine for you.
writeStrIL.EmitWriteLine("The value of this current instance is:");
// Here, you will do the hard work yourself. First, you need to create
// the string we will be passing and obtain the correct WriteLine overload
// for said string. In the below case, you are substituting in two values,
// so the chosen overload is Console.WriteLine(string, object, object).
String inStr = "({0}, {1})";
Type[] wlParams = new Type[] {typeof(string),
typeof(object),
typeof(object)};
// We need the MethodInfo to pass into EmitCall later.
MethodInfo writeLineMI = typeof(Console).GetMethod(
"WriteLine",
wlParams);
// Push the string with the substitutions onto the stack.
// This is the first argument for WriteLine - the string one.
writeStrIL.Emit(OpCodes.Ldstr, inStr);
// Since the second argument is an object, and it corresponds to
// to the substitution for the value of our integer field, you
// need to box that field to an object. First, push a reference
// to the current instance, and then push the value stored in
// field 'x'. We need the reference to the current instance (stored
// in local argument index 0) so Ldfld can load from the correct
// instance (this one).
writeStrIL.Emit(OpCodes.Ldarg_0);
writeStrIL.Emit(OpCodes.Ldfld, xField);
// Now, we execute the box opcode, which pops the value of field 'x',
// returning a reference to the integer value boxed as an object.
writeStrIL.Emit(OpCodes.Box, typeof(int));
// Atop the stack, you'll find our string inStr, followed by a reference
// to the boxed value of 'x'. Now, you need to likewise box field 'y'.
writeStrIL.Emit(OpCodes.Ldarg_0);
writeStrIL.Emit(OpCodes.Ldfld, yField);
writeStrIL.Emit(OpCodes.Box, typeof(int));
// Now, you have all of the arguments for your call to
// Console.WriteLine(string, object, object) atop the stack:
// the string InStr, a reference to the boxed value of 'x', and
// a reference to the boxed value of 'y'.
// Call Console.WriteLine(string, object, object) with EmitCall.
writeStrIL.EmitCall(OpCodes.Call, writeLineMI, null);
// Lastly, EmitWriteLine can also output the value of a field
// using the overload EmitWriteLine(FieldInfo).
writeStrIL.EmitWriteLine("The value of 'x' is:");
writeStrIL.EmitWriteLine(xField);
writeStrIL.EmitWriteLine("The value of 'y' is:");
writeStrIL.EmitWriteLine(yField);
// Since we return no value (void), the the ret opcode will not
// return the top stack value.
writeStrIL.Emit(OpCodes.Ret);
return pointTypeBld.CreateType();
}
public static void Main() {
object[] ctorParams = new object[2];
Console.Write("Enter a integer value for X: ");
string myX = Console.ReadLine();
Console.Write("Enter a integer value for Y: ");
string myY = Console.ReadLine();
Console.WriteLine("---");
ctorParams[0] = Convert.ToInt32(myX);
ctorParams[1] = Convert.ToInt32(myY);
Type ptType = CreateDynamicType();
object ptInstance = Activator.CreateInstance(ptType, ctorParams);
ptType.InvokeMember("WritePoint",
BindingFlags.InvokeMethod,
null,
ptInstance,
new object[0]);
}
}
Related
I'm using reflection to loop through a Type's properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type) explicitly, but I'd rather do it in one line. Is there a programmatic equivalent of default?
In case of a value type use Activator.CreateInstance and it should work fine.
When using reference type just return null
public static object GetDefault(Type type)
{
if(type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
In the newer version of .net such as .net standard, type.IsValueType needs to be written as type.GetTypeInfo().IsValueType
Why not call the method that returns default(T) with reflection ? You can use GetDefault of any type with:
public object GetDefault(Type t)
{
return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
}
public T GetDefaultGeneric<T>()
{
return default(T);
}
You can use PropertyInfo.SetValue(obj, null). If called on a value type it will give you the default. This behavior is documented in .NET 4.0 and in .NET 4.5.
If you're using .NET 4.0 or above and you want a programmatic version that isn't a codification of rules defined outside of code, you can create an Expression, compile and run it on-the-fly.
The following extension method will take a Type and get the value returned from default(T) through the Default method on the Expression class:
public static T GetDefaultValue<T>()
{
// We want an Func<T> which returns the default.
// Create that expression here.
Expression<Func<T>> e = Expression.Lambda<Func<T>>(
// The default value, always get what the *code* tells us.
Expression.Default(typeof(T))
);
// Compile and return the value.
return e.Compile()();
}
public static object GetDefaultValue(this Type type)
{
// Validate parameters.
if (type == null) throw new ArgumentNullException("type");
// We want an Func<object> which returns the default.
// Create that expression here.
Expression<Func<object>> e = Expression.Lambda<Func<object>>(
// Have to convert to object.
Expression.Convert(
// The default value, always get what the *code* tells us.
Expression.Default(type), typeof(object)
)
);
// Compile and return the value.
return e.Compile()();
}
You should also cache the above value based on the Type, but be aware if you're calling this for a large number of Type instances, and don't use it constantly, the memory consumed by the cache might outweigh the benefits.
Why do you say generics are out of the picture?
public static object GetDefault(Type t)
{
Func<object> f = GetDefault<object>;
return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null);
}
private static T GetDefault<T>()
{
return default(T);
}
This is optimized Flem's solution:
using System.Collections.Concurrent;
namespace System
{
public static class TypeExtension
{
//a thread-safe way to hold default instances created at run-time
private static ConcurrentDictionary<Type, object> typeDefaults =
new ConcurrentDictionary<Type, object>();
public static object GetDefaultValue(this Type type)
{
return type.IsValueType
? typeDefaults.GetOrAdd(type, Activator.CreateInstance)
: null;
}
}
}
The chosen answer is a good answer, but be careful with the object returned.
string test = null;
string test2 = "";
if (test is string)
Console.WriteLine("This will never be hit.");
if (test2 is string)
Console.WriteLine("Always hit.");
Extrapolating...
string test = GetDefault(typeof(string));
if (test is string)
Console.WriteLine("This will never be hit.");
I do the same task like this.
//in MessageHeader
private void SetValuesDefault()
{
MessageHeader header = this;
Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this);
}
//in ObjectPropertyHelper
public static void SetPropertiesToDefault<T>(T obj)
{
Type objectType = typeof(T);
System.Reflection.PropertyInfo [] props = objectType.GetProperties();
foreach (System.Reflection.PropertyInfo property in props)
{
if (property.CanWrite)
{
string propertyName = property.Name;
Type propertyType = property.PropertyType;
object value = TypeHelper.DefaultForType(propertyType);
property.SetValue(obj, value, null);
}
}
}
//in TypeHelper
public static object DefaultForType(Type targetType)
{
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
}
Equivalent to Dror's answer but as an extension method:
namespace System
{
public static class TypeExtensions
{
public static object Default(this Type type)
{
object output = null;
if (type.IsValueType)
{
output = Activator.CreateInstance(type);
}
return output;
}
}
}
The Expressions can help here:
private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>();
private object GetTypedNull(Type type)
{
Delegate func;
if (!lambdasMap.TryGetValue(type, out func))
{
var body = Expression.Default(type);
var lambda = Expression.Lambda(body);
func = lambda.Compile();
lambdasMap[type] = func;
}
return func.DynamicInvoke();
}
I did not test this snippet, but i think it should produce "typed" nulls for reference types..
Slight adjustments to #Rob Fonseca-Ensor's solution: The following extension method also works on .Net Standard since I use GetRuntimeMethod instead of GetMethod.
public static class TypeExtensions
{
public static object GetDefault(this Type t)
{
var defaultValue = typeof(TypeExtensions)
.GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { })
.MakeGenericMethod(t).Invoke(null, null);
return defaultValue;
}
public static T GetDefaultGeneric<T>()
{
return default(T);
}
}
...and the according unit test for those who care about quality:
[Fact]
public void GetDefaultTest()
{
// Arrange
var type = typeof(DateTime);
// Act
var defaultValue = type.GetDefault();
// Assert
defaultValue.Should().Be(default(DateTime));
}
/// <summary>
/// returns the default value of a specified type
/// </summary>
/// <param name="type"></param>
public static object GetDefault(this Type type)
{
return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null;
}
This should work:
Nullable<T> a = new Nullable<T>().GetValueOrDefault();
If you already create an object, you can try...
var yourObj = new yourObj();
var properties = yourObj.GetType().GetProperties();
foreach (var p in properties)
{
// you can get default value for each property
var defaultValue = p.GetValue(yourObj, null);
}
Platform: .NET framework 4.5.1, C#
I am attempting to call the constructor for a class, not knowing the generic type at run-time and wondering how I could do this. Based on other answers I have read, it’s clear that I need to rely on Reflection.
I have tried a method that includes me getting the MethodInfo array of the constructors and use that, however I am still struggling to put everything together. Below my classes.
I have a parent abstract class, defined like below.
public abstract class ParentClass {
public string name {get;}
public CustomEnum type {get;}
public object value {get;}
public ParentClass(string name, CustomEnum type, object value = null){
this.name = name;
this.type = type;
this.value = value;
}
}
One of the many implementations of the abstract class depends on a GenericType, defined like below.
public class ChildClass<GenericType> : ParentClass {
public delegate GenericType FunctionPointer(ExternalObject object);
public override string name {get;}
public override CustomEnum type {get;}
public FunctionPointer mappingFunction = null;
private ExternalObject _value {get;}
private List<GenericType> mappedValues = null;
private override object value {get => getValue(); set => setValue(value); }
public ChildClass(string name, CustomEnum type, ExternalObject value = null, FunctionPointer mappingFunction = null){
this.name = name;
this.type = type;
this._value = value;
this.mappingFunction = mappingFunction;
populateList(value);
}
private void populateList(ExternalObject value){
if(this.mappingFunction != null){
if(value != null){
this.mappedValues = new List<GenericType>();
foreach(var item in value){
GenericType valueToAdd = mappingFunction.Invoke(value);
this.mappedValues.Add(valueToAdd);
}
}
}
}
private object getValue(){
if(this.mappingFunction == null){
return this._value;
}
else {
return this.mappedValues;
}
}
private void setValue(object value){
this._value = value;
if(this.mappingFunction != null){
populateList(this._value);
}
}
}
This is how I have the process code set up:
public ParentClass[] getValues(ParentClass[] inputParameters){
ParentClass[] outputParameters = null;
if(inputParameters != null){
List<ParentClass> outputList = new List<ParentClass>();
foreach(ParentClass inputParameter in inputParameters){
object value = obtainValue(inputParameter);
ParentClass populatedParameter = populateParameter(inputParameter, value);
outputList.Add(populatedParameter);
}
outputParameters = outputList.ToArray<ParentClass>();
}
return outputParameters;
}
The method I am specifically trying to code for, is as follows:
private ParentClass populateParameter(ParentClass inputParameter, object value){
ParentClass populatedParameter = null;
if(inputParameter != null){
switch(inputParameter.type){
case CustomEnum.WITHOUT_GENERIC_TYPE:
[...]
break;
case CustomEnum.WITH_GENERIC_TYPE:
populatedParameter = populateGenericParameter(inputParameter, (ExternalObject) value);
break;
}
}
return populatedParameter;
}
I am stuck trying to understand how to craft the below method:
private ParentClass populateGenericParameter(ParentClass inputParameter, ExternalObject value) {
ParentClass populatedParameter = null;
FieldInfo functionPointer = null;
Type genericType = typeof(ChildClass<>).MakeGenericType(new object[] { inputParameter.getType() });
FieldInfo[] parameterFields = genericType.GetFields();
if(parameterFields != null){
const string functionPointerString = "FunctionPointer";
foreach(FieldInfo parameterField in parameterFields){
if(parameterField.ToString().ToUpper().Contains(functionPointerString.ToUpper()) == true){
functionPointer = parameterField;
}
}
}
ConstructorInfo[] allConstructors = genericType.GetConstructors();
if(allConstructors != null && allConstructor.Length > 0){
ConstructorInfo constructor = allConstructor[0];
object[] constructorParameters = new object[] {parameter.name, parameter.type, value, functionPointer.GetValue(null) };
populatedParameter = (ChildClass<>) constructor.Invoke(constructorParameters);
}
return populatedParameter;
}
So, the problem is with the constructorParameters object and the Invoke method.
The "functionPointer.GetValue(null)" throws an exception saying that "non-static field requires a target".
The casting of ChildClass when invoking the constructor is a compile-time error, and so far the only way to get around it has been to replace it with the ParentClass.
I am new to reflection, so looking forward to read how to get around this problem. I have visited other topics as well, and that has led me to try to use the ConstructorInfo and FieldInfo arrays. I seem stuck here though. I hope what I am trying to achieve is possible.
Ok, so I figured out the answer. Leaving it here for people that may need it in the future.
First we create the method that will use reflection:
private ParentClass populateGenericParameter(ParentClass inputParameter, ExternalObject value) {
const string methodToInvoke = "initializeParameter";
ParentClass populatedParameter = null;
try {
MethodInfo method = typeof(this).GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Type type = typeof(ChildClass<>).MakeGenericType(new Type[] {inputParameter.GetType()}).GetGenericArguments()[0].GetGenericArguments()[0];
if(type != null) {
MethodInfo genericMethod = method.MakeGenericMethod(type);
object[] methodArguments = new object[] {inputParameter, value};
populatedParameter = (ParentClass) genericMethod.Invoke(obj: this, parameters: methodArguments);
}
}
catch(Exception e) {
//logging here
}
return populatedParameter;
}
Then, we create the method that will be triggered by reflection:
private ChildClass<GenericType> initializeParameter<GenericType>(ChildClass<GenericType> inputParameter, ExternalObject value){
ChildClass<GenericType> populatedParameter = null;
if(inputParameter != null){
populatedParameter = new ChildClass<GenericType>(parameter.name, parameter.type, value, parameter.mappingFunction);
}
return populatedParameter
}
I need a TypeConverter that, idealy, translates a String to a type safe enum class (CountryIso) without having to write a converter for every type safe enum I'm about to make.
While I managed to get the following to work:
CountryIso cI = (CountryIso) "1";
I just can't get it to work with generics! The following sample doesn't work, but why?
TypeDescriptor.AddProvider(new ExplicitCastDescriptionProvider<CountryIso>(), typeof(CountryIso));
var descriptor = TypeDescriptor.GetConverter(typeof(CountryIso));
var result = descriptor.ConvertFrom("1");
I currently have a generic TypeConverter implementation:
public class ExplicitCastConverter<T>: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
// Always true: the type determines if a cast is available or not
return true;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
String dummy = (String) value;
//CountryIso tst = (CountryIso) value; // Allowed, no problem casting
//CountryIso tst = (CountryIso) dummy; // Allowed, no problem casting
//var dum_001 = (T) ((String) value); // Does not compile
//var dumdum = (T) value; // Invalid case exception
//var hoot = (T) Convert.ChangeType(value, typeof (T)); // Invalid cast exception
return null;
}
}
The Provider is as follows:
//thanks: http://groups.google.com/group/wpf-disciples/browse_thread/thread/9f7bb40b7413fcd
public class ExplicitCastDescriptionProvider<T> : TypeDescriptionProvider //where T:TypeSafeEnum
{
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return new ImplicitCastDescription<T>();
}
}
public class ImplicitCastDescription<T>: CustomTypeDescriptor //where T:TypeSafeEnum
{
public override TypeConverter GetConverter()
{
return new ExplicitCastConverter<T>();
}
}
I have a type safe enum implementation CountryIso (thanks StackOverflow!):
public sealed class CountryIso: TypeSafeEnum
{
private static readonly Dictionary<int, CountryIso> InstanceDict = new Dictionary<int, CountryIso>();
public static readonly CountryIso NL = new CountryIso(1, "NL", "Netherlands");
public static readonly CountryIso BE = new CountryIso(2, "BE", "Belgium");
private CountryIso(int value, String name, String description): base(value,name,description)
{
InstanceDict.Add(value, this);
}
public static Dictionary<int, CountryIso> Instances
{
get { return new Dictionary<int, CountryIso>(InstanceDict); }
}
public static explicit operator CountryIso(String i)
{
int index;
return Int32.TryParse(i,out index) ? InstanceDict[index] : null;
}
}
Which inherits from TypeSafeEnum:
public class TypeSafeEnum
{
protected TypeSafeEnum(int value, String name, String description)
{
Name = name;
Value = value;
Description = description;
}
public int Value{ get; private set; }
public String Name { get; private set; }
public String Description { get; private set; }
}
One option: use reflection
The problem lies with the static nature of the CountryIso members and (mostly) the casting operators. This prevents any blueprint definition enabling a generic typeconverter to know it can cast the CountryIso type safe enum. Also, you cannot cast 'down': a TypeSafeEnum can never become a CountryIso. Which is logical, but doesn't help.
[ Using reflection ]
Introduced a generic interface defining a casting method:
public interface ICast<out T>
{
T Cast(String obj);
}
Apply interface to CountryIso
public sealed class CountryIso: TypeSafeEnum , ICast<CountryIso>
Add interface as contstraint to the converter class
public class ExplicitCastConverter<T>: TypeConverter where T: ICast<T>
Add a (non-static) cast method to my CountryIso:
public new CountryIso Cast(String obj)
{
int index;
return Int32.TryParse(obj, out index) ? InstanceDict[index] : null;
}
Added a default static member to my type-safe-enum:
private static readonly CountryIso DefaultTypeSafeEnum = new CountryIso(
-1,
null,
null
);
Implement the ConvertFrom(..) in the Converter class:
T defaultMember = (T)typeof(T).GetField(
"DefaultTypeSafeEnum",
BindingFlags.NonPublic | BindingFlags.Static
).GetValue(null);
return defaultMember.Cast((String) value);
[ Type safe enum security ]
It's still possible to create & insert new instances of CountryIso via reflection (especially when using the InstanceDict for easy instance access!) Some sample code:
ConstructorInfo ci = typeof (T).GetConstructor(
BindingFlags.NonPublic|BindingFlags.Instance,
null,
CallingConventions.Standard,
new [] {typeof (int), typeof (String), typeof (String)},
new ParameterModifier[0]
);
CountryIso countryIso = (CountryIso) ci.Invoke(new object[]{30, "ZB", "Zanzibar"});
I now consider the usage of the private InstanceDict member a security hole (not a big one, since I'm not programming an API for the outside world, but still...)
In C# 3.0 you can create anonymous class with the following syntax
var o1 = new { Id = 1, Name = "Foo" };
Is there a way to dynamic create these anonymous class to a variable?
Example:
var o1 = new { Id = 1, Name = "Foo" };
var o2 = new { SQ = 2, Birth = DateTime.Now };
Dynamic create Example:
var o1 = DynamicNewAnonymous(new NameValuePair("Id", 1), new NameValuePair("Name", "Foo"));
var o2 = DynamicNewAnonymous(new NameValuePair("SQ", 2), new NameValuePair("Birth",
DateTime.Now));
Beacuse I need to do:
dynamic o1 = new ExpandObject();
o1."ID" = 1; <--"ID" is dynamic name
o1."Name" = "Foo"; <--"Name" is dynamic name
And Scene1:
void ShowPropertiesValue(object o)
{
Type oType = o.GetType();
foreach(var pi in oType.GetProperties())
{
Console.WriteLine("{0}={1}", pi.Name, pi.GetValue(o, null));
}
}
if I call:
dynamic o1 = new ExpandObject();
o1.Name = "123";
ShowPropertiesValue(o1);
It can't show the result:
Name = 123
And also I how to Convert the ExpandoObject to AnonymouseType ?
Type type = o1.GetType();
type.GetProperties(); <--I hope it can get all property of o1
Last, I modify ShowPropertiesValue() method
void ShowPropertiesValue(object o)
{
if( o is static object ) <--How to check it is dynamic or static object?
{
Type oType = o.GetType();
foreach(var pi in oType.GetProperties())
{
Console.WriteLine("{0}={1}", pi.Name, pi.GetValue(o, null));
}
}
else if( o is dynamic object ) <--How to check it is dynamic or static object?
{
foreach(var pi in ??? ) <--How to get common dynamic object's properties info ?
{
Console.WriteLine("{0}={1}", pi.Name, pi.GetValue(o, null));
}
}
}
How to implement DynamicNewAnonymous method or how to modify the ShowPropertiesValue()?
My motivations is:
dynamic o1 = new MyDynamic();
o1.Name = "abc";
Type o1Type = o1.GetType();
var props = o1Type.GetProperties(); <--I hope can get the Name Property
If i can hook dynamicObject's GetType Method, and Compel convert to strongly-typed Type.
The above Seamless code can work fine.
Anonymous types are just regular types that are implicitly declared. They have little to do with dynamic.
Now, if you were to use an ExpandoObject and reference it through a dynamic variable, you could add or remove fields on the fly.
edit
Sure you can: just cast it to IDictionary<string, object>. Then you can use the indexer.
You use the same casting technique to iterate over the fields:
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
foreach (var property in (IDictionary<string, object>)employee)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33
The above code and more can be found by clicking on that link.
You can create an ExpandoObject like this:
IDictionary<string,object> expando = new ExpandoObject();
expando["Name"] = value;
And after casting it to dynamic, those values will look like properties:
dynamic d = expando;
Console.WriteLine(d.Name);
However, they are not actual properties and cannot be accessed using Reflection. So the following statement will return a null:
d.GetType().GetProperty("Name")
Of cause it's possible to create dynamic classes using very cool ExpandoObject class.
But recently I worked on project and faced that Expando Object is serealized in not the same format on xml as an simple Anonymous class, it was pity =( , that is why I decided to create my own class and share it with you. It's using reflection and dynamic directive , builds Assembly, Class and Instance truly dynamicly. You can add, remove and change properties that is included in your class on fly
Here it is :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using static YourNamespace.DynamicTypeBuilderTest;
namespace YourNamespace
{
/// This class builds Dynamic Anonymous Classes
public class DynamicTypeBuilderTest
{
///
/// Create instance based on any Source class as example based on PersonalData
///
public static object CreateAnonymousDynamicInstance(PersonalData personalData, Type dynamicType, List<ClassDescriptorKeyValue> classDescriptionList)
{
var obj = Activator.CreateInstance(dynamicType);
var propInfos = dynamicType.GetProperties();
classDescriptionList.ForEach(x => SetValueToProperty(obj, propInfos, personalData, x));
return obj;
}
private static void SetValueToProperty(object obj, PropertyInfo[] propInfos, PersonalData aisMessage, ClassDescriptorKeyValue description)
{
propInfos.SingleOrDefault(x => x.Name == description.Name)?.SetValue(obj, description.ValueGetter(aisMessage), null);
}
public static dynamic CreateAnonymousDynamicType(string entityName, List<ClassDescriptorKeyValue> classDescriptionList)
{
AssemblyName asmName = new AssemblyName();
asmName.Name = $"{entityName}Assembly";
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule($"{asmName.Name}Module");
TypeBuilder typeBuilder = moduleBuilder.DefineType($"{entityName}Dynamic", TypeAttributes.Public);
classDescriptionList.ForEach(x => CreateDynamicProperty(typeBuilder, x));
return typeBuilder.CreateTypeInfo().AsType();
}
private static void CreateDynamicProperty(TypeBuilder typeBuilder, ClassDescriptorKeyValue description)
{
CreateDynamicProperty(typeBuilder, description.Name, description.Type);
}
///
///Creation Dynamic property (from MSDN) with some Magic
///
public static void CreateDynamicProperty(TypeBuilder typeBuilder, string name, Type propType)
{
FieldBuilder fieldBuider = typeBuilder.DefineField($"{name.ToLower()}Field",
propType,
FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(name,
PropertyAttributes.HasDefault,
propType,
null);
MethodAttributes getSetAttr =
MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig;
MethodBuilder methodGetBuilder =
typeBuilder.DefineMethod($"get_{name}",
getSetAttr,
propType,
Type.EmptyTypes);
ILGenerator methodGetIL = methodGetBuilder.GetILGenerator();
methodGetIL.Emit(OpCodes.Ldarg_0);
methodGetIL.Emit(OpCodes.Ldfld, fieldBuider);
methodGetIL.Emit(OpCodes.Ret);
MethodBuilder methodSetBuilder =
typeBuilder.DefineMethod($"set_{name}",
getSetAttr,
null,
new Type[] { propType });
ILGenerator methodSetIL = methodSetBuilder.GetILGenerator();
methodSetIL.Emit(OpCodes.Ldarg_0);
methodSetIL.Emit(OpCodes.Ldarg_1);
methodSetIL.Emit(OpCodes.Stfld, fieldBuider);
methodSetIL.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(methodGetBuilder);
propertyBuilder.SetSetMethod(methodSetBuilder);
}
public class ClassDescriptorKeyValue
{
public ClassDescriptorKeyValue(string name, Type type, Func<PersonalData, object> valueGetter)
{
Name = name;
ValueGetter = valueGetter;
Type = type;
}
public string Name;
public Type Type;
public Func<PersonalData, object> ValueGetter;
}
///
///Your Custom class description based on any source class for example
/// PersonalData
public static IEnumerable<ClassDescriptorKeyValue> GetAnonymousClassDescription(bool includeAddress, bool includeFacebook)
{
yield return new ClassDescriptorKeyValue("Id", typeof(string), x => x.Id);
yield return new ClassDescriptorKeyValue("Name", typeof(string), x => x.FirstName);
yield return new ClassDescriptorKeyValue("Surname", typeof(string), x => x.LastName);
yield return new ClassDescriptorKeyValue("Country", typeof(string), x => x.Country);
yield return new ClassDescriptorKeyValue("Age", typeof(int?), x => x.Age);
yield return new ClassDescriptorKeyValue("IsChild", typeof(bool), x => x.Age < 21);
if (includeAddress)
yield return new ClassDescriptorKeyValue("Address", typeof(string), x => x?.Contacts["Address"]);
if (includeFacebook)
yield return new ClassDescriptorKeyValue("Facebook", typeof(string), x => x?.Contacts["Facebook"]);
}
///
///Source Data Class for example
/// of cause you can use any other class
public class PersonalData
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Country { get; set; }
public int Age { get; set; }
public Dictionary<string, string> Contacts { get; set; }
}
}
}
It is also very simple to use DynamicTypeBuilder, you just need put few lines like this:
public class ExampleOfUse
{
private readonly bool includeAddress;
private readonly bool includeFacebook;
private readonly dynamic dynamicType;
private readonly List<ClassDescriptorKeyValue> classDiscriptionList;
public ExampleOfUse(bool includeAddress = false, bool includeFacebook = false)
{
this.includeAddress = includeAddress;
this.includeFacebook = includeFacebook;
this.classDiscriptionList = DynamicTypeBuilderTest.GetAnonymousClassDescription(includeAddress, includeFacebook).ToList();
this.dynamicType = DynamicTypeBuilderTest.CreateAnonymousDynamicType("VeryPrivateData", this.classDiscriptionList);
}
public object Map(PersonalData privateInfo)
{
object dynamicObject = DynamicTypeBuilderTest.CreateAnonymousDynamicInstance(privateInfo, this.dynamicType, classDiscriptionList);
return dynamicObject;
}
}
I hope that this code snippet help somebody =) Enjoy!
I'm in a situation where I'd like to instantiate an object of a type that will be determined at runtime. I also need to perform an explicit cast to that type.
Something like this:
static void castTest(myEnum val)
{
//Call a native function that returns a pointer to a structure
IntPtr = someNativeFunction(..params..);
//determine the type of the structure based on the enum value
Type structType = getTypeFromEnum(val);
structType myStruct = (structType)Marshal.PtrToStructure(IntPtr, structType);
}
This is obviously not valid code, but I hope it conveys the essence of what I'm trying to do. The method I'm actually working on will have to perform the marshaling operation on ~35 different types. I have several other methods that will need to do something similar with the same set of types. So, I'd like to isolate the type-determining logic from these methods so that I only need to write it once, and so that the methods stay clean and readable.
I must admit to being a total novice at design. Could anyone suggest a good approach to this problem? I suspect there might be an appropriate design pattern that I'm unaware of.
There are several ways you can create an object of a certain type on the fly, one is:
// determine type here
var type = typeof(MyClass);
// create an object of the type
var obj = (MyClass)Activator.CreateInstance(type);
And you'll get an instance of MyClass in obj.
Another way is to use reflection:
// get type information
var type = typeof(MyClass);
// get public constructors
var ctors = type.GetConstructors(BindingFlags.Public);
// invoke the first public constructor with no parameters.
var obj = ctors[0].Invoke(new object[] { });
And from one of ConstructorInfo returned, you can "Invoke()" it with arguments and get back an instance of the class as if you've used a "new" operator.
You can mostly do what you're describing, but since you don't know the type at compile-time, you'll have to keep the instance loosely-typed; check its type at each point you use it, and cast it appropriately then (this will not be necessary with c# 4.0, which supports dynamics):
Type type = CustomGetTypeMethod();
var obj = Activator.CreateInstance(type);
...
if(obj is MyCustomType)
{
((MyCustomType)obj).Property1;
}
else if (obj is MyOtherCustomType)
{
((MyOtherCustomType)obj).Property2;
}
I think you're looking for Activator.CreateInstance
Creating an instance of a run-time determined Type is easy, using Activator.CreateInstance, as others have mentioned. However, casting it, as you do in your example on the Marshal.PtrToStructure line is not possible, as the type has to be known at compile time for casting. Also, note that Activator.CreateInstance can not be used in conjunction with an IntPtr.
If your types have a common base class (other than Object), you can cast it to said base type and call functions on that. Otherwise, calling functions will only be possible using reflection.
So either:
static void castTest(myEnum val)
{
//Call a native function that returns a pointer to a structure
IntPtr val = someNativeFunction(..params..);
//determine the type of the structure based on the enum value
Type structType = getTypeFromEnum(val);
BaseClass myStruct = (BaseClass)Marshal.PtrToStructure(IntPtr, structType);
myStruct.SomeFunctionDeclaredInBaseClass();
}
Or:
static void castTest(myEnum val)
{
//Call a native function that returns a pointer to a structure
IntPtr val = someNativeFunction(..params..);
//determine the type of the structure based on the enum value
Type structType = getTypeFromEnum(val);
object myStruct = Marshal.PtrToStructure(IntPtr, structType);
MemberInfo[] function = FindMembers(MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
(MemberFilter)delegate(MemberInfo info, object filter)
{
return info.Name == filter.ToString();
}, "SomeFunction");
if (mi.Length > 0 && mi[0] is MethodInfo)
((MethodInfo)mi[0]).Invoke(myStruct, ..params..);
}
You could go dynamic:
using System;
namespace TypeCaster
{
class Program
{
internal static void Main(string[] args)
{
Parent p = new Parent() { name = "I am the parent", type = "TypeCaster.ChildA" };
dynamic a = Convert.ChangeType(new ChildA(p.name), Type.GetType(p.type));
Console.WriteLine(a.Name);
p.type = "TypeCaster.ChildB";
dynamic b = Convert.ChangeType(new ChildB(p.name), Type.GetType(p.type));
Console.WriteLine(b.Name);
}
}
internal class Parent
{
internal string type { get; set; }
internal string name { get; set; }
internal Parent() { }
}
internal class ChildA : Parent
{
internal ChildA(string name)
{
base.name = name + " in A";
}
public string Name
{
get { return base.name; }
}
}
internal class ChildB : Parent
{
internal ChildB(string name)
{
base.name = name + " in B";
}
public string Name
{
get { return base.name; }
}
}
}
methodName = NwSheet.Cells[rCnt1, cCnt1 - 2].Value2;
Type nameSpace=typeof(ReadExcel);
Type metdType = Type.GetType(nameSpace.Namespace + "." + methodName);
//ConstructorInfo magicConstructor = metdType.GetConstructor(Type.EmptyTypes);
//object magicClassObject = magicConstructor.Invoke(new object[] { });
object magicClassObject = Activator.CreateInstance(metdType);
MethodInfo mthInfo = metdType.GetMethod("fn_"+methodName);
StaticVariable.dtReadData.Clear();
for (iCnt = cCnt1 + 4; iCnt <= ShtRange.Columns.Count; iCnt++)
{
temp = NwSheet.Cells[1, iCnt].Value2;
StaticVariable.dtReadData.Add(temp.Trim(), Convert.ToString(NwSheet.Cells[rCnt1, iCnt].Value2));
}
//if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_AddNum" || Convert.ToString(NwSheet.Cells[rCnt1, cCnt1 - 2].Value2) == "fn_SubNum")
//{
// //StaticVariable.intParam1 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 4].Value2);
// //StaticVariable.intParam2 = Convert.ToInt32(NwSheet.Cells[rCnt1, cCnt1 + 5].Value2);
// object[] mParam1 = new object[] { Convert.ToInt32(StaticVariable.dtReadData["InParam1"]), Convert.ToInt32(StaticVariable.dtReadData["InParam2"]) };
// object result = mthInfo.Invoke(this, mParam1);
// StaticVariable.intOutParam1 = Convert.ToInt32(result);
// NwSheet.Cells[rCnt1, cCnt1 + 2].Value2 = Convert.ToString(StaticVariable.intOutParam1) != "" ? Convert.ToString(StaticVariable.intOutParam1) : String.Empty;
//}
//else
//{
object[] mParam = new object[] { };
mthInfo.Invoke(magicClassObject, mParam);