簡體   English   中英

如何將對象的屬性指定為可選/必需?

[英]How to specify properties of an object as optional/required?

我正在嘗試找到將對象屬性標記為必需/可選/忽略的最佳方法。

public enum classtype
{
    A,
    B,
    C,
    D
}
class example
{
    public classtype type { get; set; }
    public string a { get; set; }
    public string b { get; set; }
    public string c { get; set; }
    public int d { get; set; }
}

到目前為止我在做什么:

public static void DoSomething(List<example> examples)

我想要的是這樣的:

public static void DoSomething(List<example> examples)
{
    foreach (example ex in examples)
    {
        foreach (PropertyInfo prop in ex.GetType().GetProperties())
        {
            if (prop.isRequired)
            {
                DoSomethingElse(prop);
            }
            else if (prop.isOptional)
            {
                DoThis(prop);
            }
            ...
        }
    
    }
}

IE

  • -type.A:a.req、b.opt、c.req、d.ign
    -type.B:a.ign、b.req、c.opt、d.req
    -...

目標是有一種方法來迭代對象及其屬性。

我正在考慮使用字典來定義類型,但這並不是實現這一點的最有效方法。

您可以嘗試使用屬性。



class Example
{
    [UI(Type = UIType.Required)]
    public string a { get; set; }

    [UI(Type = UIType.Required)]
    public string b { get; set; }
}

那么你也能

PropertyInfo property = ...
var uis = property.GetCustomAttributes(typeof(UIAttribute), inherit: false) as UIAttribute[];
if (uis == null) ...
var ui = ui[0];
switch a 
{
   UIType.Required => ...
   ...
}

我解決這個問題的方法是利用策略模式

我會將您的Example轉換為:

public abstract class Example
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public int D { get; set; }

    public abstract void DoSomething();
}

DoSomething方法是我們想要完成繁重工作的地方。 派生類可以像原來的規則一樣創建,例如:

public class ExampleA : Example
{
    public override void DoSomething()
    {
        Console.WriteLine("Doing something A");
    }
}

public class ExampleB : Example
{
    public override void DoSomething()
    {
        Console.WriteLine("Doing something B");
    }
}

現在您的代碼只需要做:

public static void DoSomething(List<Example> examples)
{
    foreach(Example ex in examples)
    {
        ex.DoSomething();
    }
}

如果您想通過ClassType枚舉創建Example ,您可以通過以下工廠創建它:

public class ExampleFactory
{
    private readonly List<Type> types = new();

    public ExampleFactory()
    {
        types.AddRange(Assembly.GetAssembly(typeof(Example))
                                ?.GetTypes()
                                .Where(t => t.IsSubclassOf(typeof(Example))) ?? Type.EmptyTypes);
    }
    
    public Example Create(ClassType type)
    {
        var typeToCreate = types.FirstOrDefault(t => t.Name.EndsWith(type.ToString()));
        if (typeToCreate == null)
        {
            throw new ArgumentException($"No type found for {type}");
        }
        return (Example)Activator.CreateInstance(typeToCreate)!;
    }
}

可以這樣稱呼:

// Only create once
ExampleFactory factory = new ExampleFactory();
var example = factory.Create(ClassType.A);

工廠基於命名約定工作,它必須在末尾具有類類型的后綴(即 ExampleA),但這可以是您想要的任何內容。 您可以修改工廠以接受構造函數參數。

如果您想冒險(如果您想查看此示例,請告訴我),您可以將工廠更改為源代碼生成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM