Use of the PropertyGrid Control 3

Source: Internet
Author: User
Tags emit

The first class (written in C ):

Public static class ObjectWrapperFactory
{
// Method attributes for get _ * set _ * methods (property accessors)
Private static readonly MethodAttributes getSetAttr = MethodAttributes. Public | MethodAttributes. SpecialName | MethodAttributes. HideBySig;

Public static ObjectWrapper CreateWrapper (object instance)
{
Return InternalCreateWrapper (instance, null, false );
}

Public static ObjectWrapper CreateWrapperWithVisibleProperties (object instance, string [] propertyNames)
{
If (propertyNames = null)
PropertyNames = new string [] {};

Return InternalCreateWrapper (instance, propertyNames, true );
}

Public static ObjectWrapper CreateWrapperWithHiddenProperties (object instance, string [] propertyNames)
{
If (propertyNames = null)
PropertyNames = new string [] {};

Return InternalCreateWrapper (instance, propertyNames, false );
}

Private static ObjectWrapper InternalCreateWrapper (object instance, string [] propertyNames, bool makeVisible)
{
If (instance = null)
Throw new ArgumentNullException ("instance ");

// Create assembly to hold generated wrapper type
AssemblyName assemblyName = new AssemblyName ("ObjectWrapperAssembly ");
AssemblyBuilder assemblyBuilder = Thread. GetDomain (). DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess. RunAndSave );

// Create module to store Type information in
ModuleBuilder moduleBuilder = assemblyBuilder. DefineDynamicModule ("ObjectWrapperModule. dll ");

// Start creating object wrapper type
TypeBuilder wrapperClass = moduleBuilder. DefineType ("GeneratedClasses. ObjectWrapper", TypeAttributes. Public );

// Add field to keep reference to wrapped object instance
FieldBuilder wrappedInstanceField = wrapperClass. DefineField ("wrappedInstance", instance. GetType (), FieldAttributes. Private );

// Create constructor, that takes wrapped object instance as parameter
CreateConstructor (wrappedInstanceField, wrapperClass, instance );

// Create properties, that are wrappers for instance object properties
PropertyInfo [] propertyCollection = instance. GetType (). GetProperties ();

If (propertyCollection! = Null)
Foreach (PropertyInfo p in propertyCollection)
{
If (propertyNames = null)
{
CreateProperty (p, wrapperClass, wrappedInstanceField );
}
Else
{
If (makeVisible)
{
If (ContainsName (propertyNames, p. Name ))
Createproperty (p, wrapperclass, wrappedinstancefield );
}
Else
{
If (! Containsname (propertynames, P. Name ))
CreateProperty (p, wrapperClass, wrappedInstanceField );
}
}
}

// Build the System. Type
Type wrapperType = wrapperClass. CreateType ();
// (AssemblyBuilder) wrapperType. Assembly). Save ("ObjectWrapperModule. dll ");

// Create wrapper object instance
Object wrapper = Activator. CreateInstance (wrapperType, instance );
Return new ObjectWrapper (instance, wrapper );
}

Private static void CreateConstructor (FieldBuilder instanceField, TypeBuilder typeBuilder, object instance)
{
// Add constructor to take wrapped instance as parameter
Type [] constructorarguments = {instance. GetType ()};
Constructorbuilder constructor = typebuilder. defineconstructor (methodattributes. Public, callingconventions. Standard, constructorarguments );

// The constructor callits superclass constructor. The constructor stores its argument in the private field.
Ilgenerator constructoril = constructor. getilgenerator ();

Constructorinfo superconstructor = typeof (object). getconstructor (type. emptytypes );

ConstructorIL. Emit (OpCodes. Ldarg_0 );
ConstructorIL. Emit (OpCodes. Call, superConstructor );
ConstructorIL. Emit (OpCodes. Ldarg_0 );
ConstructorIL. Emit (OpCodes. Ldarg_1 );
ConstructorIL. Emit (OpCodes. stdes, instanceField );
ConstructorIL. Emit (OpCodes. Ret );
}

Private static void CreateProperty (PropertyInfo propertyInfo, TypeBuilder typeBuilder, FieldBuilder instanceField)
{
// Build wrapper properties, that are mapped to wrapped object properties
PropertyBuilder wrappedInstancePropBldr = typeBuilder. DefineProperty (propertyInfo. Name,
PropertyInfo. Attributes,
PropertyInfo. PropertyType,
Null
);

// Create property getters
CreatePropertyGetter (propertyInfo, wrappedInstancePropBldr, typeBuilder, instanceField );

// Create property setters
CreatePropertySetter (propertyInfo, wrappedInstancePropBldr, typeBuilder, instanceField );

// Create property attributes to display them correctly in the property grid
CreateCustomAttributes (propertyInfo, wrappedInstancePropBldr );
}

Private static void CreatePropertyGetter (PropertyInfo propertyInfo, PropertyBuilder propertyBuilder, TypeBuilder typeBuilder, FieldBuilder instanceField)
{
If (propertyInfo. GetGetMethod () = null)
Return;

MethodBuilder wrappedInstanceGetPropMthdBldr =
TypeBuilder. DefineMethod ("get _" + propertyInfo. Name,
GetSetAttr,
PropertyInfo. PropertyType,
Type. EmptyTypes );

// Method invokes get _ * method of the wrapped class.
ILGenerator wrappedInstanceGetIL = wrappedInstanceGetPropMthdBldr. GetILGenerator ();

WrappedInstanceGetIL. Emit (OpCodes. Ldarg_0 );
WrappedInstanceGetIL. Emit (OpCodes. lddes, instanceField );
Wrappedinstancegetil. emit (Opcodes. callvirt, propertyinfo. getgetmethod ());
Wrappedinstancegetil. emit (Opcodes. Ret );

Propertybuilder. setgetmethod (wrappedinstancegetpropmthdbldr );
}

Private Static void createpropertysetter (propertyinfo, propertybuilder, typebuilder, fieldbuilder instancefield)
{
If (propertyinfo. getsetmethod () = NULL)
Return;

MethodBuilder wrappedInstanceSetPropMthdBldr =
TypeBuilder. DefineMethod ("set _" + propertyInfo. Name,
GetSetAttr,
Null,
New Type [] {propertyInfo. PropertyType });

// Method invokes set _ * method of the wrapped class.
ILGenerator wrappedInstanceSetIL = wrappedInstanceSetPropMthdBldr. GetILGenerator ();

WrappedInstanceSetIL. Emit (OpCodes. Ldarg_0 );
WrappedInstanceSetIL. Emit (OpCodes. lddes, instanceField );
WrappedInstanceSetIL. Emit (OpCodes. Ldarg_1 );
WrappedInstanceSetIL. Emit (OpCodes. Callvirt, propertyInfo. GetSetMethod ());
WrappedInstanceSetIL. Emit (OpCodes. Ret );

PropertyBuilder. SetSetMethod (wrappedInstanceSetPropMthdBldr );
}

Private static void CreateCustomAttributes (PropertyInfo propertyInfo, PropertyBuilder propertyBuilder)
{
Array customAttributes = propertyInfo. GetCustomAttributes (true );
ConstructorInfo ctor = null;
Object [] ctorArgs = null;

// In order for properties to be displayed properly inside the property grid
// It is necessary to set appropriate BrowsableAttribute, DescriptionAttribute, CategoryAttribute,
// DisplayNameAttribute attribute values (cocould be more attributes applicable ).
If (customAttributes! = Null)
Foreach (Attribute attribute in customAttributes)
{
Ctor = null;
CtorArgs = null;

If (attribute is BrowsableAttribute)
{
BrowsableAttribute a = attribute as BrowsableAttribute;
Ctor = typeof (BrowsableAttribute). GetConstructor (new Type [] {typeof (bool )});
CtorArgs = new object [] {a. Browsable };
}

If (attribute is DescriptionAttribute)
{
DescriptionAttribute a = attribute as DescriptionAttribute;
Ctor = typeof (DescriptionAttribute). GetConstructor (new Type [] {typeof (string )});
CtorArgs = new object [] {a. Description };
}

If (attribute is CategoryAttribute)
{
CategoryAttribute a = attribute as CategoryAttribute;
Ctor = typeof (CategoryAttribute). GetConstructor (new Type [] {typeof (string )});
CtorArgs = new object [] {a. Category };
}

If (attribute is DisplayNameAttribute)
{
DisplayNameAttribute a = attribute as DisplayNameAttribute;
Ctor = typeof (DisplayNameAttribute). GetConstructor (new Type [] {typeof (string )});
CtorArgs = new object [] {a. DisplayName };
}

If (ctor! = Null & ctorArgs! = Null)
PropertyBuilder. SetCustomAttribute (new CustomAttributeBuilder (ctor, ctorArgs ));
}

// Property grid by default does not allow editing object properties, but sometimes it is necessary
// To fill in value as a string (I. e. when filling System. Windows. Control. ContentControl. Content value
// For Windows Presentation Foundation ContentControl). For that purpose we add
// TypeConverter (typeof (StringConverter) attribute to such properties.
If (propertyInfo. PropertyType. Equals (typeof (object )))
{
TypeConverterAttribute a = new TypeConverterAttribute ();
Ctor = typeof (typeconverterattribute). getconstructor (New Type [] {typeof (system. Type )});
Ctorargs = new object [] {typeof (stringconverter )};
Propertybuilder. setcustomattribute (New customattributebuilder (ctor, ctorargs ));
}
}

Private Static bool containsname (string [] names, string nametofind)
{
Foreach (string name in names)
{
If (name = nameToFind)
Return true;
}

Return false;
}
}

// Class that stores both references to a real object instance and its wrapper.
Public class ObjectWrapper
{
Private object _ wrappedInstance;

Public object WrappedInstance
{
Get {return _ wrappedInstance ;}
}

Private object _ wrapper;

Public object Wrapper
{
Get {return _ wrapper ;}
}

Public ObjectWrapper (object element, object wrappedElement)
{
If (element = null)
Throw new ArgumentNullException ("element ");

If (wrappedElement = null)
Throw new ArgumentNullException ("wrappedElement ");

_ WrappedInstance = element;
_ Wrapper = wrappedElement;
}

Public bool Contains (object element)
{
If (element = null)
Return false;

Return (element = _ wrappedInstance );
}
}

Use (written in vb)

Dim propertyNames () As String = {"id", "dt", "dataType"} 'is the property name

Me. propertyGrid. SelectedObject = ObjectWrapperFactory. CreateWrapperWithHiddenProperties (new EntityValueObject, propertyNames). Wrapper

 

 

Advantages:

As described in the previous article, features must be used to control the visibility of certain attributes before compilation. You can use code control to display dynamic control attributes at runtime.

 

 

Learning from http://www.codeproject.com/, huh, huh!

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.