in src/Microsoft.VisualStudio.Composition/Configuration/MetadataViewGenerator.cs [153:280]
private static TypeInfo GenerateInterfaceViewProxyType(Type viewType)
{
// View type is an interface let's cook an implementation
TypeInfo proxyType;
TypeBuilder proxyTypeBuilder;
Type[] interfaces = { viewType };
var proxyModuleBuilder = GetProxyModuleBuilder(viewType.GetTypeInfo());
proxyTypeBuilder = proxyModuleBuilder.DefineType(
string.Format(CultureInfo.InvariantCulture, "_proxy_{0}_{1}", viewType.FullName, Guid.NewGuid()),
TypeAttributes.Public,
typeof(object),
interfaces);
// Generate field
const string metadataFieldName = "metadata";
FieldBuilder metadataFieldBuilder = proxyTypeBuilder.DefineField(
metadataFieldName,
CtorArgumentTypes[0],
FieldAttributes.Private | FieldAttributes.InitOnly);
const string metadataDefaultFieldName = "metadataDefault";
FieldBuilder metadataDefaultFieldBuilder = proxyTypeBuilder.DefineField(
metadataDefaultFieldName,
CtorArgumentTypes[1],
FieldAttributes.Private | FieldAttributes.InitOnly);
// Implement Constructor
ConstructorBuilder proxyCtor = proxyTypeBuilder.DefineConstructor(MethodAttributes.Private, CallingConventions.Standard, CtorArgumentTypes);
ILGenerator proxyCtorIL = proxyCtor.GetILGenerator();
// : base()
proxyCtorIL.Emit(OpCodes.Ldarg_0);
proxyCtorIL.Emit(OpCodes.Call, ObjectCtor);
// this.metadata = metadata;
proxyCtorIL.Emit(OpCodes.Ldarg_0);
proxyCtorIL.Emit(OpCodes.Ldarg_1);
proxyCtorIL.Emit(OpCodes.Stfld, metadataFieldBuilder);
// this.metadataDefault = metadataDefault;
proxyCtorIL.Emit(OpCodes.Ldarg_0);
proxyCtorIL.Emit(OpCodes.Ldarg_2);
proxyCtorIL.Emit(OpCodes.Stfld, metadataDefaultFieldBuilder);
proxyCtorIL.Emit(OpCodes.Ret);
foreach (PropertyInfo propertyInfo in viewType.GetAllProperties())
{
string propertyName = propertyInfo.Name;
Type[] propertyTypeArguments = new Type[] { propertyInfo.PropertyType };
Type[]? optionalModifiers = null;
Type[]? requiredModifiers = null;
// PropertyInfo does not support GetOptionalCustomModifiers and GetRequiredCustomModifiers on Silverlight
optionalModifiers = propertyInfo.GetOptionalCustomModifiers();
requiredModifiers = propertyInfo.GetRequiredCustomModifiers();
Array.Reverse(optionalModifiers);
Array.Reverse(requiredModifiers);
// Generate property
PropertyBuilder proxyPropertyBuilder = proxyTypeBuilder.DefineProperty(
propertyName,
PropertyAttributes.None,
propertyInfo.PropertyType,
propertyTypeArguments);
// Generate "get" method implementation.
MethodBuilder getMethodBuilder = proxyTypeBuilder.DefineMethod(
string.Format(CultureInfo.InvariantCulture, "get_{0}", propertyName),
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
CallingConventions.HasThis,
propertyInfo.PropertyType,
requiredModifiers,
optionalModifiers,
Type.EmptyTypes,
null,
null);
proxyTypeBuilder.DefineMethodOverride(getMethodBuilder, propertyInfo.GetGetMethod()!);
ILGenerator getMethodIL = getMethodBuilder.GetILGenerator();
// object value;
LocalBuilder valueLocal = getMethodIL.DeclareLocal(typeof(object));
// this.metadata.TryGetValue(propertyName, out value);
getMethodIL.Emit(OpCodes.Ldarg_0);
getMethodIL.Emit(OpCodes.Ldfld, metadataFieldBuilder);
getMethodIL.Emit(OpCodes.Ldstr, propertyName);
getMethodIL.Emit(OpCodes.Ldloca_S, valueLocal);
getMethodIL.Emit(OpCodes.Callvirt, MdvDictionaryTryGet);
// If that succeeded, prepare to return.
Label returnLabel = getMethodIL.DefineLabel();
getMethodIL.Emit(OpCodes.Brtrue_S, returnLabel);
// Otherwise get the value from the default metadata dictionary.
getMethodIL.Emit(OpCodes.Ldarg_0);
getMethodIL.Emit(OpCodes.Ldfld, metadataDefaultFieldBuilder);
getMethodIL.Emit(OpCodes.Ldstr, propertyName);
getMethodIL.Emit(OpCodes.Callvirt, MdvDictionaryIndexer);
getMethodIL.Emit(OpCodes.Stloc_0);
getMethodIL.MarkLabel(returnLabel);
getMethodIL.Emit(OpCodes.Ldloc_0);
getMethodIL.Emit(propertyInfo.PropertyType.GetTypeInfo().IsValueType ? OpCodes.Unbox_Any : OpCodes.Isinst, propertyInfo.PropertyType);
getMethodIL.Emit(OpCodes.Ret);
proxyPropertyBuilder.SetGetMethod(getMethodBuilder);
}
// Implement the static factory
//// public static object Create(IReadOnlyDictionary<string, object?>, IReadOnlyDictionary<string, object?>)
//// {
//// return new <ProxyClass>(dictionary);
//// }
MethodBuilder factoryMethodBuilder = proxyTypeBuilder.DefineMethod(MetadataViewGenerator.MetadataViewFactoryName, MethodAttributes.Public | MethodAttributes.Static, typeof(object), CtorArgumentTypes);
ILGenerator factoryIL = factoryMethodBuilder.GetILGenerator();
factoryIL.Emit(OpCodes.Ldarg_0);
factoryIL.Emit(OpCodes.Ldarg_1);
factoryIL.Emit(OpCodes.Newobj, proxyCtor);
factoryIL.Emit(OpCodes.Ret);
// Finished implementing the type
proxyType = proxyTypeBuilder.CreateTypeInfo()!;
return proxyType!;
}