1

我正在研究 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) 中选择的类型的方法。

  1. 如果 BusinessLayer 属性是 Business.customer__business,那么 MethodToInvoke 应该允许我选择 GetAll 或 GetById。
  2. 如果 BusinessLayer 属性是 Business.user__business,那么 MethodToInvoke 应该允许我选择 GetAllByCriteria 或 GetById 或 GetBy。
  3. 如果 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
            }
        }
    }
}

谢谢。

4

1 回答 1

0

你快到了,你需要做的是:

  1. 在您的控件中,在主属性(业务类类型)中,当值更改时,将从属属性(方法名称)设置为 null 或任何其他有意义的值。
  2. 在从属属性类型转换器中GetStandardValues,将转换context.Instnace为您的控件类型,然后获取主属性的值(业务类类型)并返回可能值的列表(方法名称)。

就这样。以上评论将解决您的问题,但您或未来的读者可能会发现以下示例很有趣。

示例 - 属性编辑器选择一个类及其方法之一

在此示例中,我创建了一个具有两个新属性的自定义控件:

  • BusinessClassType:对于这个属性,我使用自定义类型转换器来显示业务类列表。
  • MethodName:对于这个属性,我使用自定义类型转换器来显示业务方法列表。

我没有依赖命名约定来查找业务类,而是创建了一个属性BusinessClass;同样对于方法,我创建了BusinessMethod属性,所以我不会在下拉列表中显示所有方法,只显示那些您标记为业务方法的方法。它在某种程度上类似于 WFC 服务合同和方法合同中的想法。

在此处输入图像描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
public class MyCustomControl : TextBox
{
    private Type type;
    [TypeConverter(typeof(BusinessClassTypeConverter))]
    public Type BusinessClassType
    {
        get { return type; }
        set
        {
            if (type != value)
            {
                type = value;
                BusinessMethodName = null;
            }
        }
    }
    [TypeConverter(typeof(BusinessMethodNameConverter))]
    public string BusinessMethodName { get; set; }
}
public class BusinessClassTypeConverter : TypeConverter
{
    public override bool GetStandardValuesExclusive
        (ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool GetStandardValuesSupported
        (ITypeDescriptorContext pContext)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues
        (ITypeDescriptorContext pContext)
    {
        return new StandardValuesCollection(
            GetProjectTypes(pContext).OrderBy(x => x.FullName).ToList());
    }
    public override bool CanConvertFrom(ITypeDescriptorContext context,
        Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom
        (ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
            return GetTypeFromName(context, (string)value);
        return base.ConvertFrom(context, culture, value);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context,
        Type destinationType)
    {
        return base.CanConvertTo(context, destinationType);
    }
    public override object ConvertTo(ITypeDescriptorContext context,
        CultureInfo culture, object value, Type destinationType)
    {
        return base.ConvertTo(context, culture, value, destinationType);
    }
    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.GetCustomAttributes(true)
                .OfType<BusinessClassAttribute>().Any() &&
                !item.FullName.StartsWith("System")
            ).ToList();
        return types;
    }
    private Type GetTypeFromName(IServiceProvider serviceProvider, string typeName)
    {
        ITypeResolutionService typeResolutionSvc = 
            (ITypeResolutionService)serviceProvider
            .GetService(typeof(ITypeResolutionService));
        return typeResolutionSvc.GetType(typeName);
    }
}
public class BusinessMethodNameConverter : TypeConverter
{
    public override bool GetStandardValuesSupported(
        ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool GetStandardValuesExclusive(
        ITypeDescriptorContext context)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues(
        ITypeDescriptorContext context)
    {
        var type = ((MyCustomControl)context.Instance).BusinessClassType;
        if (type != null)
        {
            return new StandardValuesCollection(type.GetMethods()
                .Where(x => x.GetCustomAttributes(true)
                .OfType<BusinessMethodAttribute>().Any())
                .Select(x => x.Name).ToList());
        }
        return new StandardValuesCollection(Array.Empty<object>());
    }
    public override bool CanConvertFrom(ITypeDescriptorContext context,
        Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context,
        CultureInfo culture, object value)
    {
        if (value is string)
            return (string)value;
        return base.ConvertFrom(context, culture, value);
    }
}
public class BusinessClassAttribute : Attribute { }
public class BusinessMethodAttribute : Attribute { }

[BusinessClass]
public class MyBusinessClass1
{
    [BusinessMethod]
    public void Method11() { }
    public void Method12() { }
    [BusinessMethod]
    public void Method13() { }
}
public class MyBusinessClass2
{
}
[BusinessClass]
public class MyBusinessClass3
{
    [BusinessMethod]
    public void Method31() { }
    public void Method32() { }
    [BusinessMethod]
    public void Method33() { }
}

更多信息

您可能还会发现以下链接很有用:

于 2021-12-24T18:53:02.990 回答