?? typedobjectlistview.cs
字號(hào):
public delegate String TypedCellToolTipGetterDelegate(OLVColumn column, T modelObject);
public virtual TypedCellToolTipGetterDelegate CellToolTipGetter
{
set {
if (value == null)
this.olv.CellToolTipGetter = null;
else
this.olv.CellToolTipGetter = delegate(OLVColumn col, Object x) {
return value(col, (T)x);
};
}
}
public virtual HeaderToolTipGetterDelegate HeaderToolTipGetter
{
get { return this.olv.HeaderToolTipGetter; }
set { this.olv.HeaderToolTipGetter = value; }
}
//--------------------------------------------------------------------------------------
// Commands
/// <summary>
/// This method will generate AspectGetters for any column that has an AspectName.
/// </summary>
public virtual void GenerateAspectGetters()
{
for (int i = 0; i < this.ListView.Columns.Count; i++)
this.GetColumn(i).GenerateAspectGetter();
}
}
/// <summary>
/// A type-safe wrapper around an OLVColumn
/// </summary>
/// <typeparam name="T"></typeparam>
public class TypedColumn<T> where T : class
{
public TypedColumn(OLVColumn column)
{
this.column = column;
}
private OLVColumn column;
public delegate Object TypedAspectGetterDelegate(T rowObject);
public delegate void TypedAspectPutterDelegate(T rowObject, Object newValue);
public delegate Object TypedGroupKeyGetterDelegate(T rowObject);
public delegate Object TypedImageGetterDelegate(T rowObject);
public TypedAspectGetterDelegate AspectGetter
{
get { return this.aspectGetter; }
set {
this.aspectGetter = value;
if (value == null)
this.column.AspectGetter = null;
else
this.column.AspectGetter = delegate(object x) {
return this.aspectGetter((T)x);
};
}
}
private TypedAspectGetterDelegate aspectGetter;
public TypedAspectPutterDelegate AspectPutter
{
get { return aspectPutter; }
set {
this.aspectPutter = value;
if (value == null)
this.column.AspectPutter = null;
else
this.column.AspectPutter = delegate(object x, object newValue) {
this.aspectPutter((T)x, newValue);
};
}
}
private TypedAspectPutterDelegate aspectPutter;
public TypedImageGetterDelegate ImageGetter
{
get { return imageGetter; }
set {
this.imageGetter = value;
if (value == null)
this.column.ImageGetter = null;
else
this.column.ImageGetter = delegate(object x) {
return this.imageGetter((T)x);
};
}
}
private TypedImageGetterDelegate imageGetter;
public TypedGroupKeyGetterDelegate GroupKeyGetter
{
get { return groupKeyGetter; }
set {
this.groupKeyGetter = value;
if (value == null)
this.column.GroupKeyGetter = null;
else
this.column.GroupKeyGetter = delegate(object x) {
return this.groupKeyGetter((T)x);
};
}
}
private TypedGroupKeyGetterDelegate groupKeyGetter;
#region Dynamic methods
/// <summary>
/// Generate an aspect getter that does the same thing as the AspectName,
/// except without using reflection.
/// </summary>
/// <remarks>
/// <para>
/// If you have an AspectName of "Owner.Address.Postcode", this will generate
/// the equivilent of: <code>this.AspectGetter = delegate (object x) {
/// return x.Owner.Address.Postcode;
/// }
/// </code>
/// </para>
/// <para>
/// If AspectName is empty, this method will do nothing, otherwise
/// this will replace any existing AspectGetter.
/// </para>
/// </remarks>
public void GenerateAspectGetter()
{
if (!String.IsNullOrEmpty(this.column.AspectName))
this.AspectGetter = this.GenerateAspectGetter(typeof(T), this.column.AspectName);
}
/// <summary>
/// Generates an aspect getter method dynamically. The method will execute
/// the given dotted chain of selectors against a model object given at runtime.
/// </summary>
/// <param name="type">The type of model object to be passed to the generated method</param>
/// <param name="path">A dotted chain of selectors. Each selector can be the name of a
/// field, property or parameter-less method.</param>
/// <returns>A typed delegate</returns>
private TypedAspectGetterDelegate GenerateAspectGetter(Type type, string path)
{
DynamicMethod getter = new DynamicMethod(String.Empty,
typeof(Object), new Type[] { type }, type, true);
this.GenerateIL(type, path, getter.GetILGenerator());
return (TypedAspectGetterDelegate)getter.CreateDelegate(typeof(TypedAspectGetterDelegate));
}
/// <summary>
/// This method generates the actual IL for the method.
/// </summary>
/// <param name="type"></param>
/// <param name="path"></param>
/// <param name="il"></param>
private void GenerateIL(Type type, string path, ILGenerator il)
{
// Push our model object onto the stack
il.Emit(OpCodes.Ldarg_0);
// Generate the IL to access each part of the dotted chain
string[] parts = path.Split('.');
for (int i = 0; i < parts.Length; i++ ) {
type = this.GeneratePart(il, type, parts[i], (i==parts.Length-1));
if (type == null)
break;
}
// If the object to be returned is a value type (e.g. int, bool), it
// must be boxed, since the delegate returns an Object
if (type != null && type.IsValueType && !typeof(T).IsValueType)
il.Emit(OpCodes.Box, type);
il.Emit(OpCodes.Ret);
}
private Type GeneratePart(ILGenerator il, Type type, string pathPart, bool isLastPart)
{
// TODO: Generate check for null
// Find the first member with the given nam that is a field, property, or parameter-less method
List<MemberInfo> infos = new List<MemberInfo>(type.GetMember(pathPart));
MemberInfo info = infos.Find(delegate(MemberInfo x) {
if (x.MemberType == MemberTypes.Field || x.MemberType == MemberTypes.Property)
return true;
if (x.MemberType == MemberTypes.Method)
return ((MethodInfo)x).GetParameters().Length == 0;
else
return false;
});
// If we couldn't find anything with that name, pop the current result and return an error
if (info == null) {
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldstr, String.Format("'{0}' is not a parameter-less method, property or field of type '{1}'", pathPart, type.FullName));
return null;
}
// Generate the correct IL to access the member. We remember the type of object that is going to be returned
// so that we can do a method lookup on it at the next iteration
Type resultType = null;
switch (info.MemberType) {
case MemberTypes.Method:
MethodInfo mi = (MethodInfo)info;
if (mi.IsVirtual)
il.Emit(OpCodes.Callvirt, mi);
else
il.Emit(OpCodes.Call, mi);
resultType = mi.ReturnType;
break;
case MemberTypes.Property:
PropertyInfo pi = (PropertyInfo)info;
il.Emit(OpCodes.Call, pi.GetGetMethod());
resultType = pi.PropertyType;
break;
case MemberTypes.Field:
FieldInfo fi = (FieldInfo)info;
il.Emit(OpCodes.Ldfld, fi);
resultType = fi.FieldType;
break;
}
// If the method returned a value type, and something is going to call a method on that value,
// we need to load its address onto the stack, rather than the object itself.
if (resultType.IsValueType && !isLastPart) {
LocalBuilder lb = il.DeclareLocal(resultType);
il.Emit(OpCodes.Stloc, lb);
il.Emit(OpCodes.Ldloca, lb);
}
return resultType;
}
#endregion
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -