Skip to content

Instantly share code, notes, and snippets.

@aetos382
Last active November 16, 2020 23:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aetos382/bc5cc03ae1fed9a8b35533ae57913a88 to your computer and use it in GitHub Desktop.
Save aetos382/bc5cc03ae1fed9a8b35533ae57913a88 to your computer and use it in GitHub Desktop.
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