Reflection GetMethod. select a more specific method - c#

i want to get the method but there are more then one overload. For example in object i tried to get 'Equals'. When using
public virtual bool Equals(object obj);
public static bool Equals(object objA, object objB);
writing typeof(Object).GetMethod("Equals") got me an exception, writing typeof(Object).GetMethod("public virtual bool Equals(object obj)") got me null. How do i specify which method i want in this case?

Use one of the overloads that lets you specify the parameter types.
For example:
var staticMethod = typeof(Object).GetMethod("Equals",
BindingFlags.Static | BindingFlags.Public,
null,
new Type[] { typeof(object), typeof(object) },
null);
var instanceMethod = typeof(Object).GetMethod("Equals",
BindingFlags.Instance | BindingFlags.Public,
null,
new Type[] { typeof(object) },
null);
Or alternatively:
var staticMethod = typeof(Object).GetMethod("Equals",
new Type[] { typeof(object), typeof(object) });
var instanceMethod = typeof(Object).GetMethod("Equals",
new Type[] { typeof(object) });

MethodInfo methodInfo = typeof(object).GetMethod("Equals", new Type[] { typeof(object), typeof(object) });

You can try this code..
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var actionName = filterContext.RouteData.Values["action"].ToString();
var ctlr = filterContext.Controller as Controller;
if (ctlr == null) return;
var invoker = ctlr.ActionInvoker as ControllerActionInvoker;
if (invoker == null) return;
var invokerType = invoker.GetType();
var getCtlrDescMethod = invokerType.GetMethod("GetControllerDescriptor", BindingFlags.NonPublic | BindingFlags.Instance);
var ctlrDesc = getCtlrDescMethod.Invoke(invoker, new object[] {ctlr.ControllerContext}) as ControllerDescriptor;
var findActionMethod = invokerType.GetMethod("FindAction", BindingFlags.NonPublic | BindingFlags.Instance);
var actionDesc = findActionMethod.Invoke(invoker, new object[] { ctlr.ControllerContext, ctlrDesc, actionName }) as ReflectedActionDescriptor;
if (actionDesc == null) return;
if (actionDesc.MethodInfo.ReturnType == typeof (ActionResult))
{
// you're in
}
}

Related

Cant bind RouteValueDictionary as HtmlAttributes to EditorFor

I'm trying to make a simple HtmlHelper to create a EditorFor that deal with List<T> index childs.
I did some like this
public static IHtmlString EditorFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper
, Expression<Func<TModel, TValue>> exp
, Expression<Func<TModel, int>> expId
, object htmlAttributes = null)
{
//Id value
var id = expId.Compile().Invoke(htmlHelper.ViewData.Model);
//Prefix
var prefix = htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix;
//Propertyname
var propertyName = ExpressionHelper.GetExpressionText(exp);
//Create id and name for the EditorFor
var htmlId = $"{prefix}_{id}__{propertyName}";
var htmlName = $"{prefix}[{id}].{propertyName}";
//Create the must have attributes.
var attributes = new
RouteValueDictionary(
new {
id = htmlId,
#Name = htmlName
});
//if htmlAttributes paramter has values, will merge
if(htmlAttributes != null){
//merge..
foreach (var attr in new RouteValueDictionary(htmlAttributes).Where(attr => !attributes.ContainsKey(attr.Key)))
{
attributes.Add(attr.Key,attr.Value);
}
}
//Create a editor for
var editor = htmlHelper.EditorFor(exp, new
{
htmlAttributes = attributes
});
return new HtmlString(editor.ToString());
}
In the view i'm using it like
#Html.EditorFor(x => x.GradienteDeEntrada, x => x.Id)
My problem here, is that the Html markup generated is
<input count="2" keys="System.Collections.Generic.Dictionary`2+KeyCollection[System.String,System.Object]" values="System.Collections.Generic.Dictionary`2+ValueCollection[System.String,System.Object]" autocomplete="off" class=" decimal" data-val="true" data-val-number="El campo Gradiente de entrada debe ser un número." id="DatosTermicos_GradienteEntrada" name="DatosTermicos.GradienteEntrada" type="text" value="">
I try converting it to HtmlHelper with this answer or dynamic with this other but when i use any of this methods, both Id and Name are just ignored.
If I create the htmlAttributes as a object
var attributes = new { id = htmlId, #Name = htmlName };
work just fine, the problem is that I don't know how to merge it with the received parameters. How can I pass the RouteValueDictionary with my HtmlAttributes to the EditorFor?
I solve it using this answer from Abdul Rauf based on converting the RouteValueDictionary in Anonymous Object (System.Object) instead of dynamic.
This is the method
public static object FromDictToAnonymousObj<TValue>(IDictionary<string, TValue> dict)
{
var types = new Type[dict.Count];
for (int i = 0; i < types.Length; i++)
{
types[i] = typeof(TValue);
}
// dictionaries don't have an order, so we force an order based
// on the Key
var ordered = dict.OrderBy(x => x.Key).ToArray();
string[] names = Array.ConvertAll(ordered, x => x.Key);
Type type = AnonymousType.CreateType(types, names);
object[] values = Array.ConvertAll(ordered, x => (object)x.Value);
object obj = type.GetConstructor(types).Invoke(values);
return obj;
}
The AnonymousType class code :
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
/// <summary>
/// The code generated should be nearly equal to the one generated by
/// csc 12.0.31101.0 when compiling with /optimize+ /debug-. The main
/// difference is in the GetHashCode() (the base init_hash used is
/// compiler-dependant) and in the maxstack of the generated methods.
/// Note that Roslyn (at least the one present at
/// tryroslyn.azurewebsites.net) generates different code for anonymous
/// types.
/// </summary>
public static class AnonymousType
{
private static readonly ConcurrentDictionary<string, Type> GeneratedTypes = new ConcurrentDictionary<string, Type>();
private static readonly AssemblyBuilder AssemblyBuilder;
private static readonly ModuleBuilder ModuleBuilder;
private static readonly string FileName;
// Some objects we cache
private static readonly CustomAttributeBuilder CompilerGeneratedAttributeBuilder = new CustomAttributeBuilder(typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
private static readonly CustomAttributeBuilder DebuggerBrowsableAttributeBuilder = new CustomAttributeBuilder(typeof(DebuggerBrowsableAttribute).GetConstructor(new[] { typeof(DebuggerBrowsableState) }), new object[] { DebuggerBrowsableState.Never });
private static readonly CustomAttributeBuilder DebuggerHiddenAttributeBuilder = new CustomAttributeBuilder(typeof(DebuggerHiddenAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
private static readonly ConstructorInfo ObjectCtor = typeof(object).GetConstructor(Type.EmptyTypes);
private static readonly MethodInfo ObjectToString = typeof(object).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
private static readonly ConstructorInfo StringBuilderCtor = typeof(StringBuilder).GetConstructor(Type.EmptyTypes);
private static readonly MethodInfo StringBuilderAppendString = typeof(StringBuilder).GetMethod("Append", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string) }, null);
private static readonly MethodInfo StringBuilderAppendObject = typeof(StringBuilder).GetMethod("Append", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(object) }, null);
private static readonly Type EqualityComparer = typeof(EqualityComparer<>);
private static readonly Type EqualityComparerGenericArgument = EqualityComparer.GetGenericArguments()[0];
private static readonly MethodInfo EqualityComparerDefault = EqualityComparer.GetMethod("get_Default", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
private static readonly MethodInfo EqualityComparerEquals = EqualityComparer.GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public, null, new[] { EqualityComparerGenericArgument, EqualityComparerGenericArgument }, null);
private static readonly MethodInfo EqualityComparerGetHashCode = EqualityComparer.GetMethod("GetHashCode", BindingFlags.Instance | BindingFlags.Public, null, new[] { EqualityComparerGenericArgument }, null);
private static int Index = -1;
static AnonymousType()
{
var assemblyName = new AssemblyName("AnonymousTypes");
FileName = assemblyName.Name + ".dll";
AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder = AssemblyBuilder.DefineDynamicModule("AnonymousTypes", FileName);
}
public static void Dump()
{
AssemblyBuilder.Save(FileName);
}
/// <summary>
///
/// </summary>
/// <param name="types"></param>
/// <param name="names"></param>
/// <returns></returns>
public static Type CreateType(Type[] types, string[] names)
{
if (types == null)
{
throw new ArgumentNullException("types");
}
if (names == null)
{
throw new ArgumentNullException("names");
}
if (types.Length != names.Length)
{
throw new ArgumentException("names");
}
// Anonymous classes are generics based. The generic classes
// are distinguished by number of parameters and name of
// parameters. The specific types of the parameters are the
// generic arguments. We recreate this by creating a fullName
// composed of all the property names, separated by a "|"
string fullName = string.Join("|", names.Select(x => Escape(x)));
Type type;
if (!GeneratedTypes.TryGetValue(fullName, out type))
{
// We create only a single class at a time, through this lock
// Note that this is a variant of the double-checked locking.
// It is safe because we are using a thread safe class.
lock (GeneratedTypes)
{
if (!GeneratedTypes.TryGetValue(fullName, out type))
{
int index = Interlocked.Increment(ref Index);
string name = names.Length != 0 ? string.Format("<>f__AnonymousType{0}`{1}", index, names.Length) : string.Format("<>f__AnonymousType{0}", index);
TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder);
GenericTypeParameterBuilder[] generics = null;
if (names.Length != 0)
{
string[] genericNames = Array.ConvertAll(names, x => string.Format("<{0}>j__TPar", x));
generics = tb.DefineGenericParameters(genericNames);
}
else
{
generics = new GenericTypeParameterBuilder[0];
}
// .ctor
ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, generics);
constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
ILGenerator ilgeneratorConstructor = constructor.GetILGenerator();
ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor);
var fields = new FieldBuilder[names.Length];
// There are two for cycles because we want to have
// all the getter methods before all the other
// methods
for (int i = 0; i < names.Length; i++)
{
// field
fields[i] = tb.DefineField(string.Format("<{0}>i__Field", names[i]), generics[i], FieldAttributes.Private | FieldAttributes.InitOnly);
fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder);
// .ctor
constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]);
ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
if (i == 0)
{
ilgeneratorConstructor.Emit(OpCodes.Ldarg_1);
}
else if (i == 1)
{
ilgeneratorConstructor.Emit(OpCodes.Ldarg_2);
}
else if (i == 2)
{
ilgeneratorConstructor.Emit(OpCodes.Ldarg_3);
}
else if (i < 255)
{
ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1));
}
else
{
// Ldarg uses a ushort, but the Emit only
// accepts short, so we use a unchecked(...),
// cast to short and let the CLR interpret it
// as ushort
ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked((short)(i + 1)));
}
ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]);
// getter
MethodBuilder getter = tb.DefineMethod(string.Format("get_{0}", names[i]), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, generics[i], Type.EmptyTypes);
ILGenerator ilgeneratorGetter = getter.GetILGenerator();
ilgeneratorGetter.Emit(OpCodes.Ldarg_0);
ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]);
ilgeneratorGetter.Emit(OpCodes.Ret);
PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConventions.HasThis, generics[i], Type.EmptyTypes);
property.SetGetMethod(getter);
}
// ToString()
MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(string), Type.EmptyTypes);
toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
ILGenerator ilgeneratorToString = toString.GetILGenerator();
ilgeneratorToString.DeclareLocal(typeof(StringBuilder));
ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor);
ilgeneratorToString.Emit(OpCodes.Stloc_0);
// Equals
MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), new[] { typeof(object) });
equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
equals.DefineParameter(1, ParameterAttributes.None, "value");
ILGenerator ilgeneratorEquals = equals.GetILGenerator();
ilgeneratorEquals.DeclareLocal(tb);
ilgeneratorEquals.Emit(OpCodes.Ldarg_1);
ilgeneratorEquals.Emit(OpCodes.Isinst, tb);
ilgeneratorEquals.Emit(OpCodes.Stloc_0);
ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
Label equalsLabel = ilgeneratorEquals.DefineLabel();
// GetHashCode()
MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int), Type.EmptyTypes);
getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator();
ilgeneratorGetHashCode.DeclareLocal(typeof(int));
if (names.Length == 0)
{
ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0);
}
else
{
// As done by Roslyn
// Note that initHash can vary, because
// string.GetHashCode() isn't "stable" for
// different compilation of the code
int initHash = 0;
for (int i = 0; i < names.Length; i++)
{
initHash = unchecked(initHash * (-1521134295) + fields[i].Name.GetHashCode());
}
// Note that the CSC seems to generate a
// different seed for every anonymous class
ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash);
}
for (int i = 0; i < names.Length; i++)
{
// Equals()
Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i]);
MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerDefault);
MethodInfo equalityComparerTEquals = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerEquals);
ilgeneratorEquals.Emit(OpCodes.Brfalse_S, equalsLabel);
ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);
// GetHashCode();
MethodInfo EqualityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerGetHashCode);
ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
ilgeneratorGetHashCode.Emit(OpCodes.Mul);
ilgeneratorGetHashCode.Emit(OpCodes.Call, EqualityComparerDefault);
ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]);
ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, EqualityComparerGetHashCode);
ilgeneratorGetHashCode.Emit(OpCodes.Add);
// ToString()
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? string.Format("{{ {0} = ", names[i]) : string.Format(", {0} = ", names[i]));
ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
ilgeneratorToString.Emit(OpCodes.Pop);
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
ilgeneratorToString.Emit(OpCodes.Ldarg_0);
ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]);
ilgeneratorToString.Emit(OpCodes.Box, generics[i]);
ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject);
ilgeneratorToString.Emit(OpCodes.Pop);
}
// .ctor
ilgeneratorConstructor.Emit(OpCodes.Ret);
// Equals()
if (names.Length == 0)
{
ilgeneratorEquals.Emit(OpCodes.Ldnull);
ilgeneratorEquals.Emit(OpCodes.Ceq);
ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
ilgeneratorEquals.Emit(OpCodes.Ceq);
}
else
{
ilgeneratorEquals.Emit(OpCodes.Ret);
ilgeneratorEquals.MarkLabel(equalsLabel);
ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
}
ilgeneratorEquals.Emit(OpCodes.Ret);
// GetHashCode()
ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
ilgeneratorGetHashCode.Emit(OpCodes.Ret);
// ToString()
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }");
ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
ilgeneratorToString.Emit(OpCodes.Pop);
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString);
ilgeneratorToString.Emit(OpCodes.Ret);
type = tb.CreateType();
type = GeneratedTypes.GetOrAdd(fullName, type);
}
}
}
if (types.Length != 0)
{
type = type.MakeGenericType(types);
}
return type;
}
private static string Escape(string str)
{
// We escape the \ with \\, so that we can safely escape the
// "|" (that we use as a separator) with "\|"
str = str.Replace(#"\", #"\\");
str = str.Replace(#"|", #"\|");
return str;
}
}

Newtonsoft.Json AttributeProvider does not provide runtime added custom attributes

I did write a model generator to create an interface between client ViewModels and server Models.
Some model classes are serialize with [JsonObject(MemberSerialization.OptIn)] attribute and their properties are marked with [JsonProperty ...] to be serialized, in addition i have some custom attributes which need to be handled in my custom DefaultContractResolver.
Here is how I create my ModelView from any source type
public Type CreateModelView(Type sourceType) {
...
foreach (var attribute in sourceType.CustomAttributes)
typeBuilder.SetCustomAttribute(
new CustomAttributeBuilder(
attribute.Constructor,
attribute.ConstructorArguments.Select(x => x.Value).ToArray()));
...
var fields = GetFields(sourceType);
foreach (var field in fields)
CreateProperty(typeBuilder, field.Name, field.PropertyType, field.GetCustomAttributes(true));
return typeBuilder.CreateTypeInfo().AsType();
}
private void CreateProperty(TypeBuilder typeBuilder, string name, Type type, object[] customAttributes)
{
var fieldBuilder = typeBuilder.DefineField(name, type, FieldAttributes.Public);
var propertyBuilder = typeBuilder.DefineProperty(name, PropertyAttributes.HasDefault, type, null);
var GetMethodBuilder = typeBuilder.DefineMethod(
"Get" + name,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig, type,
Type.EmptyTypes);
var iLGenerator = GetMethodBuilder.GetILGenerator();
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Ldfld, fieldBuilder);
iLGenerator.Emit(OpCodes.Ret);
var SetMethodBuilder =
typeBuilder.DefineMethod("Set" + name,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
null,
new[] { type });
ILGenerator setIl = SetMethodBuilder.GetILGenerator();
Label modifyProperty = setIl.DefineLabel();
Label exitSet = setIl.DefineLabel();
setIl.MarkLabel(modifyProperty);
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, fieldBuilder);
setIl.Emit(OpCodes.Nop);
setIl.MarkLabel(exitSet);
setIl.Emit(OpCodes.Ret);
foreach (var customAttribute in customAttributes)
AddCustomAttributeToProperty(customAttribute, propertyBuilder);
propertyBuilder.SetGetMethod(GetMethodBuilder);
propertyBuilder.SetSetMethod(SetMethodBuilder);
}
/// <summary>
/// Given a custom attribute and property builder, adds an instance of custom attribute
/// to the property builder
/// </summary>
void AddCustomAttributeToProperty(object customAttribute, PropertyBuilder propBuilder)
{
var customAttributeBuilder = BuildCustomAttribute(customAttribute);
if (customAttributeBuilder != null)
{
propBuilder.SetCustomAttribute(customAttributeBuilder);
}
}
static CustomAttributeBuilder BuildCustomAttribute(object customAttribute)
{
ConstructorInfo longestCtor = null;
// Get constructor with the largest number of parameters
foreach (var cInfo in customAttribute.GetType().GetConstructors().
Where(cInfo => longestCtor == null || longestCtor.GetParameters().Length < cInfo.GetParameters().Length))
longestCtor = cInfo;
if (longestCtor == null)
{
return null;
}
// For each constructor parameter, get corresponding (by name similarity) property and get its value
var args = new object[longestCtor.GetParameters().Length];
var position = 0;
foreach (var consParamInfo in longestCtor.GetParameters())
{
var attrPropInfo = customAttribute.GetType().GetProperty(consParamInfo.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (attrPropInfo != null)
{
args[position] = attrPropInfo.GetValue(customAttribute, null);
}
else
{
args[position] = null;
var attrFieldInfo = customAttribute.GetType().GetField(consParamInfo.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (attrFieldInfo == null)
{
if (consParamInfo.ParameterType.IsValueType)
{
args[position] = Activator.CreateInstance(consParamInfo.ParameterType);
}
}
else
{
args[position] = attrFieldInfo.GetValue(customAttribute);
}
}
++position;
}
var propList = new List<PropertyInfo>();
var propValueList = new List<object>();
foreach (var attrPropInfo in customAttribute.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (!attrPropInfo.CanWrite)
{
continue;
}
object defaultValue = null;
var defaultAttributes = attrPropInfo.GetCustomAttributes(typeof(DefaultValueAttribute), true);
if (defaultAttributes.Length > 0)
{
defaultValue = ((DefaultValueAttribute)defaultAttributes[0]).Value;
}
var value = attrPropInfo.GetValue(customAttribute, null);
if (value == defaultValue)
{
continue;
}
propList.Add(attrPropInfo);
propValueList.Add(value);
}
return new CustomAttributeBuilder(longestCtor, args, propList.ToArray(), propValueList.ToArray());
}
i tested this code as well with field.CustomAttributes and result was same.
propertyBuilder.SetCustomAttribute(
new CustomAttributeBuilder(
attribute.Constructor,
attribute.ConstructorArguments.Select(x => x.Value).ToArray()));
and the problem is here in ContractResolver when the result of attributes is empty,
public class ContractResolver : DefaultContractResolver {
...
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
var propertyList = base.CreateProperties(type, memberSerialization);
foreach (var jProperty in propertyList)
{
var attributes = jProperty.AttributeProvider.GetAttributes(true);
var isBindNever = attributes.OfType<BindNeverAttribute>().Any();
var isKey = attributes.OfType<KeyAttribute>().Any();
...
}
and [JsonProperty ...] attributes are not working as well.
P.S. I can get custom attributes from this code
var PropertyType = jProperty.DeclaringType.GetProperties()
.Where(property => property.Name.ToLower() == jProperty.PropertyName.ToLower())
.FirstOrDefault();
The problem is why is jProperty.AttributeProvider.GetAttributes not working as expected,
Why [JsonProperty] not working as expected (marked properties won't serialized).
This will solve problem, however it's not efficient
public class JsonResolver : DefaultContractResolver
{
...
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var serializableMembers = base.GetSerializableMembers(objectType).Select(memberInfo => memberInfo.Name);
return objectType.GetProperties().Where(memberInfo => serializableMembers.Contains(memberInfo.Name)).Cast<MemberInfo>().ToList();
}
...
}

How can I handle generic method invocations in my DynamicObject?

I'm trying to construct a DynamicObject that is able to handle generic method invocations, but it seems that the needed API - although present in RC versions of 4.0 Framework - has been marked internal in RTM (namely, CSharpInvokeMemberBinder is now internal). Is there an equivalent for this code that would work in 4.0 RTM?
public class TransparentObject<T> : DynamicObject {
private readonly T target;
public TransparentObject(T target) {
this.target = target;
}
public override bool TryInvokeMember(
InvokeMemberBinder binder, object[] args, out object result) {
var csBinder = binder as CSharpInvokeMemberBinder;
var method = typeof(T).GetMethod(binder.Name, BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
throw new MissingMemberException(string.Format(
"Method '{0}' not found for type '{1}'", binder.Name, typeof(T)));
if (csBinder.TypeArguments.Count > 0)
method = method.MakeGenericMethod(csBinder.TypeArguments.ToArray());
result = method.Invoke(target, args);
return true;
}
}
(Code taken from http://bugsquash.blogspot.com/2009/05/testing-private-methods-with-c-40.html )
I am aware that I can use reflection to get generic type parameters here, but I'm looking for a nicer solution - if there is one.
The fastest equivalent I can guess:
private static readonly Func<InvokeMemberBinder, IList<Type>> GetTypeArguments;
static TransparentObject()
{
var type = typeof(RuntimeBinderException).Assembly.GetTypes().Where(x => x.FullName == "Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder").Single();
var dynamicMethod = new DynamicMethod("#", typeof(IList<Type>), new[] { typeof(InvokeMemberBinder) }, true);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, type);
il.Emit(OpCodes.Call, type.GetProperty("Microsoft.CSharp.RuntimeBinder.ICSharpInvokeOrInvokeMemberBinder.TypeArguments", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true));
il.Emit(OpCodes.Ret);
GetTypeArguments = (Func<InvokeMemberBinder, IList<Type>>)dynamicMethod.CreateDelegate(typeof(Func<InvokeMemberBinder, IList<Type>>));
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var method = typeof(T).GetMethod(binder.Name, BindingFlags.Public| BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null) throw new MissingMemberException(string.Format("Method '{0}' not found for type '{1}'", binder.Name, typeof(T)));
var typeArguments = GetTypeArguments(binder);
if (typeArguments.Count > 0) method = method.MakeGenericMethod(typeArguments.ToArray());
result = method.Invoke(target, args);
return true;
}

Practical example of Dynamic method?

I want to learn dynamic method and its practical example using c#.
Is there any relation between dynamic method and Reflection?
Please help me.
We are using Dynamic methods for speed up Reflection.
Here is code of our reflection optimizer. it is only 10% slower than direct call and 2000 times faster that reflection call
public class ReflectionEmitPropertyAccessor
{
private readonly bool canRead;
private readonly bool canWrite;
private IPropertyAccessor emittedPropertyAccessor;
private readonly string propertyName;
private readonly Type propertyType;
private readonly Type targetType;
private Dictionary<Type,OpCode> typeOpCodes;
public ReflectionEmitPropertyAccessor(Type targetType, string property)
{
this.targetType = targetType;
propertyName = property;
var propertyInfo = targetType.GetProperty(property);
if (propertyInfo == null)
{
throw new ReflectionOptimizerException(string.Format("Property \"{0}\" is not found in type "+ "{1}.", property, targetType));
}
canRead = propertyInfo.CanRead;
canWrite = propertyInfo.CanWrite;
propertyType = propertyInfo.PropertyType;
}
public bool CanRead
{
get { return canRead; }
}
public bool CanWrite
{
get { return canWrite; }
}
public Type TargetType
{
get { return targetType; }
}
public Type PropertyType
{
get { return propertyType; }
}
#region IPropertyAccessor Members
public object Get(object target)
{
if (canRead)
{
if (emittedPropertyAccessor == null)
{
Init();
}
if (emittedPropertyAccessor != null) return emittedPropertyAccessor.Get(target);
}
else
{
throw new ReflectionOptimizerException(string.Format("У свойства \"{0}\" нет метода get.", propertyName));
}
throw new ReflectionOptimizerException("Fail initialize of " + GetType().FullName);
}
public void Set(object target, object value)
{
if (canWrite)
{
if (emittedPropertyAccessor == null)
{
Init();
}
if (emittedPropertyAccessor != null) emittedPropertyAccessor.Set(target, value);
}
else
{
throw new ReflectionOptimizerException(string.Format("Property \"{0}\" does not have method set.", propertyName));
}
throw new ReflectionOptimizerException("Fail initialize of " + GetType().FullName);
}
#endregion
private void Init()
{
InitTypeOpCodes();
var assembly = EmitAssembly();
emittedPropertyAccessor = assembly.CreateInstance("Property") as IPropertyAccessor;
if (emittedPropertyAccessor == null)
{
throw new ReflectionOptimizerException("Shit happense in PropertyAccessor.");
}
}
private void InitTypeOpCodes()
{
typeOpCodes = new Dictionary<Type, OpCode>
{
{typeof (sbyte), OpCodes.Ldind_I1},
{typeof (byte), OpCodes.Ldind_U1},
{typeof (char), OpCodes.Ldind_U2},
{typeof (short), OpCodes.Ldind_I2},
{typeof (ushort), OpCodes.Ldind_U2},
{typeof (int), OpCodes.Ldind_I4},
{typeof (uint), OpCodes.Ldind_U4},
{typeof (long), OpCodes.Ldind_I8},
{typeof (ulong), OpCodes.Ldind_I8},
{typeof (bool), OpCodes.Ldind_I1},
{typeof (double), OpCodes.Ldind_R8},
{typeof (float), OpCodes.Ldind_R4}
};
}
private Assembly EmitAssembly()
{
var assemblyName = new AssemblyName {Name = "PropertyAccessorAssembly"};
var newAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var newModule = newAssembly.DefineDynamicModule("Module");
var dynamicType = newModule.DefineType("Property", TypeAttributes.Public);
dynamicType.AddInterfaceImplementation(typeof(IPropertyAccessor));
dynamicType.DefineDefaultConstructor(MethodAttributes.Public);
var getParamTypes = new[] { typeof(object) };
var getReturnType = typeof(object);
var getMethod = dynamicType.DefineMethod("Get",
MethodAttributes.Public | MethodAttributes.Virtual,
getReturnType,
getParamTypes);
var getIL = getMethod.GetILGenerator();
var targetGetMethod = targetType.GetMethod("get_" + propertyName);
if (targetGetMethod != null)
{
getIL.DeclareLocal(typeof(object));
getIL.Emit(OpCodes.Ldarg_1); //Load the first argument
getIL.Emit(OpCodes.Castclass, targetType); //Cast to the source type
getIL.EmitCall(OpCodes.Call, targetGetMethod, null); //Get the property value
if (targetGetMethod.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, targetGetMethod.ReturnType); //Box
}
getIL.Emit(OpCodes.Stloc_0); //Store it
getIL.Emit(OpCodes.Ldloc_0);
}
else
{
getIL.ThrowException(typeof(MissingMethodException));
}
getIL.Emit(OpCodes.Ret);
var setParamTypes = new[] { typeof(object), typeof(object) };
const Type setReturnType = null;
var setMethod = dynamicType.DefineMethod("Set",
MethodAttributes.Public | MethodAttributes.Virtual,
setReturnType,
setParamTypes);
var setIL = setMethod.GetILGenerator();
var targetSetMethod = targetType.GetMethod("set_" + propertyName);
if (targetSetMethod != null)
{
Type paramType = targetSetMethod.GetParameters()[0].ParameterType;
setIL.DeclareLocal(paramType);
setIL.Emit(OpCodes.Ldarg_1); //Load the first argument //(target object)
setIL.Emit(OpCodes.Castclass, targetType); //Cast to the source type
setIL.Emit(OpCodes.Ldarg_2); //Load the second argument
//(value object)
if (paramType.IsValueType)
{
setIL.Emit(OpCodes.Unbox, paramType); //Unbox it
if (typeOpCodes.ContainsKey(paramType)) //and load
{
var load = typeOpCodes[paramType];
setIL.Emit(load);
}
else
{
setIL.Emit(OpCodes.Ldobj, paramType);
}
}
else
{
setIL.Emit(OpCodes.Castclass, paramType); //Cast class
}
setIL.EmitCall(OpCodes.Callvirt,targetSetMethod, null); //Set the property value
}
else
{
setIL.ThrowException(typeof(MissingMethodException));
}
setIL.Emit(OpCodes.Ret);
// Load the type
dynamicType.CreateType();
return newAssembly;
}
}
implementation is aggregated from different sources and main is this CodeProject article.
You can create a method via DynamicMethod class.
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Example).Module);
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Conv_I8);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Mul);
il.Emit(OpCodes.Ret);
Fully commented example on MSDN
I should note that the development using this method is very slow and not very useful.

How can I perform a List<object>.Cast<T> using reflection when T is unknown

I've been trying to do this for a good few hours now and this is as far as I have got
var castItems = typeof(Enumerable).GetMethod("Cast")
.MakeGenericMethod(new Type[] { targetType })
.Invoke(null, new object[] { items });
This returns me
System.Linq.Enumerable+d__aa`1[MyObjectType]
whereas I need (for my ViewData) as generic list i.e.
System.Collections.Generic.List`1[MyObjectType]
Any pointers would be great
You just need to call ToList() on it afterwards:
static readonly MethodInfo CastMethod = typeof(Enumerable).GetMethod("Cast");
static readonly MethodInfo ToListMethod = typeof(Enumerable).GetMethod("ToList");
...
var castItems = CastMethod.MakeGenericMethod(new Type[] { targetType })
.Invoke(null, new object[] { items });
var list = ToListMethod.MakeGenericMethod(new Type[] { targetType })
.Invoke(null, new object[] { castItems });
Another option would be to write a single generic method in your own class to do this, and call that with reflection:
private static List<T> CastAndList(IEnumerable items)
{
return items.Cast<T>().ToList();
}
private static readonly MethodInfo CastAndListMethod =
typeof(YourType).GetMethod("CastAndList",
BindingFlags.Static | BindingFlags.NonPublic);
public static object CastAndList(object items, Type targetType)
{
return CastAndListMethod.MakeGenericMethod(new[] { targetType })
.Invoke(null, new[] { items });
}

Categories