我正在研究 N 层(实体、数据、业务和表示)的新解决方案,我需要创建一个自定义控件来加快搜索速度(该控件将在表示层中)。
这里是解决方案的结构:
Solution
Ⱶ Entities
Ⱶ customer__entity
Ⱶ user__entity
Ⱶ product__entity
Ⱶ Data
Ⱶ customer__data
Ⱶ user__data
Ⱶ product__data
Ⱶ Business
Ⱶ customer__business
Ⱶ user__business
Ⱶ product__business
Ⱶ Presentation
Ⱶ controls (folder)
Ⱶ TextSearch (custom control)
Ⱶ forms (folder)
Ⱶ frm__customer___maintenance
Ⱶ frm__user___maintenance
Ⱶ frm__product___maintenance
现在我将详细介绍业务层的类所具有的方法。
public abstract class customer__business
{
public static IEnumerable<customer__entity> GetAll() { }
public static customer__entity GetById(int id) { }
}
public abstract class user__business
{
public static IEnumerable<customer__entity> GetAllByCriteria(string criteria) { }
public static customer__entity GetById(int id) { }
public static DataTable GetBy(string criteria) { }
}
public abstract class product__business
{
public static product__entity GetById(int id) { }
public static string GetName(string criteria) { }
}
这个想法是创建一个继承自 System.Windows.Forms.TextBox 并具有 2 个自定义属性(1 => BusinessLayer 和 2 => MethodToInvoke)的 TextBox 控件。第一个属性将是 type 类型,并将使用 TypeConverter 加载业务层类。第二个属性将依赖于第一个,并且它必须列出第一个属性中选择的类型所具有的所有方法。
public class TextSearch : System.Windows.Forms.TextBox
{
[TypeConverter(typeof(BusinessLayerTypeConverter))]
public Type BusinessLayer { get; set; }
[TypeConverter(typeof(MethodToInvokeTypeConverter))]
public string MethodToInvoke { get; set; }
}
我已经准备好业务层 TypeConverter 类:
public class BusinessLayerTypeConverter : TypeConverter
{
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override bool CanConvertTo(ITypeDescriptorContext pContext, Type pDestinationType)
{
return base.CanConvertTo(pContext, pDestinationType);
}
public override object ConvertTo(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue, Type pDestinationType)
{
return base.ConvertTo(pContext, pCulture, pValue, pDestinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext pContext, Type pSourceType)
{
if (pSourceType == typeof(string))
return true;
return base.CanConvertFrom(pContext, pSourceType);
}
public override object ConvertFrom(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue)
{
if (pValue is string)
return GetTypeFromName(pContext, (string)pValue);
return base.ConvertFrom(pContext, pCulture, pValue);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext pContext)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext pContext)
{
List<Type> types = GetProjectTypes(pContext);
List<string> values = new List<string>();
foreach (Type type in types)
values.Add(type.FullName);
values.Sort();
return new StandardValuesCollection(values);
}
private List<Type> GetProjectTypes(IServiceProvider serviceProvider)
{
var typeDiscoverySvc = (ITypeDiscoveryService)serviceProvider.GetService(typeof(ITypeDiscoveryService));
var types = typeDiscoverySvc.GetTypes(typeof(object), true).Cast<Type>().Where(item => item.IsPublic && !item.FullName.StartsWith("System") && item.FullName.Contains("__business")).ToList();
return types;
}
private Type GetTypeFromName(IServiceProvider serviceProvider, string typeName)
{
ITypeResolutionService typeResolutionSvc = (ITypeResolutionService)serviceProvider.GetService(typeof(ITypeResolutionService));
return typeResolutionSvc.GetType(typeName);
}
}
这是第一个属性的结果,它可以正常工作。
我的问题是我不知道该怎么做,所以第二个属性 (MethodToInvoke) 列出了在第一个属性 (BusinessLayer) 中选择的类型的方法。
- 如果 BusinessLayer 属性是 Business.customer__business,那么 MethodToInvoke 应该允许我选择 GetAll 或 GetById。
- 如果 BusinessLayer 属性是 Business.user__business,那么 MethodToInvoke 应该允许我选择 GetAllByCriteria 或 GetById 或 GetBy。
- 如果 BusinessLayer 属性是 Business.product__business,那么 MethodToInvoke 应该允许我选择 GetById 或 GetName。
这是类 MethodToInvokeTypeConverter:
public class MethodToInvokeTypeConverter : TypeConverter
{
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override bool CanConvertTo(ITypeDescriptorContext pContext, Type pDestinationType)
{
return base.CanConvertTo(pContext, pDestinationType);
}
public override object ConvertTo(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue, Type pDestinationType)
{
return base.ConvertTo(pContext, pCulture, pValue, pDestinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext pContext, Type pSourceType)
{
if (pSourceType == typeof(string))
return true;
return base.CanConvertFrom(pContext, pSourceType);
}
public override object ConvertFrom(ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue)
{
if (pValue is string)
return GetTypeFromName(pContext, (string)pValue);
return base.ConvertFrom(pContext, pCulture, pValue);
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext pContext)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext pContext)
{
List<Type> types = GetProjectTypes(pContext);
List<string> values = new List<string>();
foreach (Type type in types)
values.Add(type.FullName);
values.Sort();
return new StandardValuesCollection(values);
}
private List<Type> GetProjectTypes(IServiceProvider serviceProvider)
{
var types = // I SUPPOSE THAT I SHOULD CODE WHAT I NEED HERE, HOWEVER I DON'T KNOW WHERE TO START.
return types;
}
private Type GetTypeFromName(IServiceProvider serviceProvider, string typeName)
{
ITypeResolutionService typeResolutionSvc = (ITypeResolutionService)serviceProvider.GetService(typeof(ITypeResolutionService));
return typeResolutionSvc.GetType(typeName);
}
}
谢谢你能给我的所有帮助。
编辑1:
控件的想法是,当将控件添加到表单时,程序员将设置 BusinessLayer 属性(将自动从业务层中的现有类加载),然后设置 MethodToInvoke 属性(将自动加载BusinessLayer 属性中所选类型的现有方法)。
在 TextSearch 控件中,我将覆盖 KeyDown 方法,以通过反射分别调用属性中选择的类型的方法(MethodToInvoke、BusinessLayer)。
public class TextSearch : System.Windows.Forms.TextBox
{
[TypeConverter(typeof(BusinessLayerTypeConverter))]
public Type BusinessLayer { get; set; }
[TypeConverter(typeof(MethodToInvokeTypeConverter))]
public string MethodToInvoke { get; set; }
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (!DesignMode)
{
if (e.KeyCode == Keys.Enter)
{
var type = BusinessLayer;
var method = MethodToInvoke;
type.GetMethod(method).Invoke(null, null);
// CODE
}
}
}
}
谢谢。

