Last active
November 16, 2020 23:36
-
-
Save aetos382/bc5cc03ae1fed9a8b35533ae57913a88 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static Func<CustomAttributeData, TAttribute> GetAttributeInstanceCreator<TAttribute>( | |
CustomAttributeData customAttributeData) | |
{ | |
var customAttributeDataParameter = Expression.Parameter(typeof(CustomAttributeData)); | |
var constructorArgumentsExpression = Expression.Property( | |
customAttributeDataParameter, | |
nameof(CustomAttributeData.ConstructorArguments)); | |
var listOfConstructorArgumentIndexer = (PropertyInfo)typeof(IList<CustomAttributeTypedArgument>).GetDefaultMembers()[0]; | |
var constructorArgumentExpressions = new List<Expression>(customAttributeData.ConstructorArguments.Count); | |
for (int i = 0; i < customAttributeData.ConstructorArguments.Count; ++i) | |
{ | |
var constructorArgumentItemExpression = Expression.Property( | |
constructorArgumentsExpression, | |
listOfConstructorArgumentIndexer, | |
Expression.Constant(i)); | |
var constructorArgumentValueExpression = Expression.Property( | |
constructorArgumentItemExpression, | |
nameof(CustomAttributeTypedArgument.Value)); | |
var constructorArgumentTypedValueExpression = Expression.Convert( | |
constructorArgumentValueExpression, | |
customAttributeData.ConstructorArguments[i].ArgumentType); | |
constructorArgumentExpressions.Add(constructorArgumentTypedValueExpression); | |
} | |
var newExpression = Expression.New( | |
customAttributeData.Constructor, | |
constructorArgumentExpressions); | |
var namedArgumentsExpression = Expression.Property( | |
customAttributeDataParameter, | |
nameof(CustomAttributeData.NamedArguments)); | |
var memberAssignments = new List<MemberAssignment>(); | |
var listOfNamedArgumentIndexer = (PropertyInfo)typeof(IList<CustomAttributeNamedArgument>).GetDefaultMembers()[0]; | |
for (int i = 0; i < customAttributeData.NamedArguments.Count; ++i) | |
{ | |
var namedArgument = customAttributeData.NamedArguments[i]; | |
var namedArgumentItemExpression = Expression.Property( | |
namedArgumentsExpression, | |
listOfNamedArgumentIndexer, | |
Expression.Constant(i)); | |
var namedArgumentTypedValueExpression = Expression.Property( | |
namedArgumentItemExpression, | |
nameof(CustomAttributeNamedArgument.TypedValue)); | |
var namedArgumentValueExpression = Expression.Property( | |
namedArgumentTypedValueExpression, | |
nameof(CustomAttributeTypedArgument.Value)); | |
var bindExpression = Expression.Bind( | |
namedArgument.MemberInfo, | |
Expression.Convert( | |
namedArgumentValueExpression, | |
namedArgument.TypedValue.ArgumentType)); | |
memberAssignments.Add(bindExpression); | |
} | |
var newAndInitExpression = Expression.MemberInit( | |
newExpression, | |
memberAssignments); | |
var lambdaExpression = Expression.Lambda<Func<CustomAttributeData, TAttribute>>( | |
newAndInitExpression, | |
customAttributeDataParameter); | |
return lambdaExpression.Compile(); | |
} | |
static void Main() | |
{ | |
var hogeAttributeData = typeof(Hoge).GetCustomAttributesData().First(b => b.AttributeType == typeof(HogeAttribute)); | |
var createHogeAttributeDelegate = GetAttributeInstanceCreator<HogeAttribute>(hogeAttributeData); | |
var hogeAttribute = createHogeAttributeDelegate(hogeAttributeData); | |
hogeAttribute.Dump(); | |
} | |
[Hoge(1, 2, P = 3, Q = 4, F = 5, G = 6)] | |
public class Hoge | |
{ | |
} | |
public class HogeAttribute : Attribute | |
{ | |
public HogeAttribute(int x, int y) | |
{ | |
this.X = x; | |
this.Y = y; | |
} | |
public int X { get; } | |
public int Y { get; } | |
public int P { get; set; } | |
public int Q { get; set; } | |
public int F; | |
public int G; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment