private DictionaryAdapterMeta CreateAdapterMeta(Type type, TypeBuilder typeBuilder, PropertyDescriptor descriptor) { var binding = FieldAttributes.Public | FieldAttributes.Static; var metaField = typeBuilder.DefineField("__meta", typeof(DictionaryAdapterMeta), binding); var constructor = CreateAdapterConstructor(typeBuilder); CreateAdapterFactoryMethod(typeBuilder, constructor); object[] typeBehaviors; var initializers = new PropertyDescriptor(); var propertyMap = GetPropertyDescriptors(type, initializers, out typeBehaviors); if (descriptor != null) { //#if DOTNET40 initializers.AddBehaviors(descriptor.MetaInitializers); //#else // initializers.AddBehaviors(descriptor.MetaInitializers.Cast<IDictionaryBehavior>()); //#endif typeBehaviors = typeBehaviors.Union(descriptor.Annotations).ToArray(); } CreateMetaProperty(typeBuilder, AdapterGetMeta, metaField); foreach (var property in propertyMap) { CreateAdapterProperty(typeBuilder, property.Value); } var implementation = typeBuilder.CreateType(); var creator = (Func <DictionaryAdapterInstance, IDictionaryAdapter>)Delegate.CreateDelegate ( typeof(Func <DictionaryAdapterInstance, IDictionaryAdapter>), implementation, "__Create" ); var meta = new DictionaryAdapterMeta(type, implementation, typeBehaviors, initializers.MetaInitializers.ToArray(), initializers.Initializers.ToArray(), propertyMap, this, creator); const BindingFlags metaBindings = BindingFlags.Public | BindingFlags.Static | BindingFlags.SetField; implementation.InvokeMember("__meta", metaBindings, null, null, new[] { meta }); return(meta); }
private static Dictionary <String, PropertyDescriptor> GetPropertyDescriptors(Type type, PropertyDescriptor initializers, out object[] typeBehaviors) { var propertyMap = new Dictionary <String, PropertyDescriptor>(); var interfaceBehaviors = typeBehaviors = ExpandBehaviors(AttributesUtil.GetInterfaceAttributes(type)).ToArray(); var defaultFetch = typeBehaviors.OfType <FetchAttribute>().Select(b => (bool?)b.Fetch).FirstOrDefault().GetValueOrDefault(); //#if DOTNET40 initializers.AddBehaviors(typeBehaviors.OfType <IDictionaryMetaInitializer>()) .AddBehaviors(typeBehaviors.OfType <IDictionaryInitializer>()); //#else // initializers.AddBehaviors(typeBehaviors.OfType<IDictionaryMetaInitializer>().Cast<IDictionaryBehavior>()) // .AddBehaviors(typeBehaviors.OfType<IDictionaryInitializer> ().Cast<IDictionaryBehavior>()); //#endif CollectProperties(type, property => { var propertyBehaviors = ExpandBehaviors(AttributesUtil.GetAttributes <object>(property)).ToArray(); var propertyDescriptor = new PropertyDescriptor(property, propertyBehaviors) .AddBehaviors(propertyBehaviors.OfType <IDictionaryBehavior>()) .AddBehaviors(interfaceBehaviors.OfType <IDictionaryBehavior>().Where(b => b is IDictionaryKeyBuilder == false)) //#if DOTNET40 .AddBehaviors(ExpandBehaviors(AttributesUtil .GetInterfaceAttributes(property.ReflectedType)) .OfType <IDictionaryKeyBuilder>()); //#else // .AddBehaviors(ExpandBehaviors(AttributesUtil // .GetInterfaceAttributes(property.ReflectedType)) // .OfType<IDictionaryKeyBuilder>() // .Cast<IDictionaryBehavior>()); //#endif AddDefaultGetter(propertyDescriptor); var propertyFetch = propertyBehaviors.OfType <FetchAttribute>().Select(b => (bool?)b.Fetch).FirstOrDefault(); propertyDescriptor.IfExists = propertyBehaviors.OfType <IfExistsAttribute>().Any(); propertyDescriptor.Fetch = propertyFetch.GetValueOrDefault(defaultFetch); foreach (var descriptorInitializer in propertyDescriptor.Behaviors.OfType <IPropertyDescriptorInitializer>()) { descriptorInitializer.Initialize(propertyDescriptor, propertyBehaviors); } //#if DOTNET40 initializers.AddBehaviors(propertyBehaviors.OfType <IDictionaryMetaInitializer>()); //#else // initializers.AddBehaviors(propertyBehaviors.OfType<IDictionaryMetaInitializer>().Cast<IDictionaryBehavior>()); //#endif PropertyDescriptor existingDescriptor; if (propertyMap.TryGetValue(property.Name, out existingDescriptor)) { var existingProperty = existingDescriptor.Property; if (existingProperty.PropertyType == property.PropertyType) { if (property.CanRead && property.CanWrite) { propertyMap[property.Name] = propertyDescriptor; } return; } } propertyMap.Add(property.Name, propertyDescriptor); }); return(propertyMap); }