【发布时间】:2021-07-14 04:38:42
【问题描述】:
我正在研究 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
}
}
}
}
谢谢。
【问题讨论】:
-
您要解决的实际问题是什么?只是创建一个通过对象列表搜索的搜索控件? winforms 设计器中是否出现了属性?这些属性实际上应该做什么?
-
MethodToInvoke 是一个字符串,在您的 GetProjectTypes 中,您应该使用反射迭代您需要的类类型并在转换器中返回方法的名称......但只是一个字符串;)
-
问题出在MethodToInvokeTypeConverter类中,不知道如何根据BusinessLayer属性中选择的类型列出方法。我想在 GetProjectTypes (ITypeDescriptorContext pContext) 方法中,我必须捕获 BusinessLayer 的值,但我不知道该怎么做(并使用反射列出该类型的所有方法。)我编辑了我的帖子(请阅读最终部分)。
-
@pedroPG 这个问题是几个月前的问题(在撰写此评论时),您最喜欢自己找到了解决方案,但主题和问题很有趣,所以我回答了这个问题并分享了一个示例以及一些链接,供未来的读者了解更多关于这个主题的信息。希望您和未来的读者发现它有用。
标签: c# .net winforms windows-forms-designer