基于字符串选择多个属性的值

3
我正在构建一个自动化工作流系统,需要根据正在读取的文件名设置4个字符串值。我有一个可以运行的switch语句,但是从下面的示例中可以看到不同文件名之间有很多共享值。因为不久将来我需要处理多达40个不同的文件名,所以我正在寻找简化这段代码的方法。
每个文件都必须分配以下属性:AccountName(账户名)、CampaignName(活动名称)、DocumentName(文档名称)和DestinationName(目标名称)。账户和活动通常在相似的文件之间共享,但文档几乎总是唯一的。请参见下面的示例。
case "Cow":
    accountName = "Farm Animals";
    campaignName = "Quadrupeds";
    documentName = "Milk Givers";
    destinationName = "Milking Line";
    break;
case "Chicken":
    accountName = "Farm Animals";
    campaignName = "Bipeds";
    documentName = "Egg Layers";
    destinationName = "Coupe";
    break;
case "Turkey":
    accountName = "Farm Animals";
    campaignName = "Bipeds";
    documentName = "Dinner";
    destinationName = "My Table";
    break;
case "Dog":
    accountName = "Farm Animals";
    campaignName = "Quadrupeds";
    documentName = "Best Friend";
    destinationName = "Front Porch";
    break;
case "Pig":
    accountName = "Farm Animals";
    campaignName = "Quadrupeds";
    documentName = "Bacon";
    destinationName = "My Plate";
    break;

我不确定字典是否是我要找的东西,或者我是否需要构建一个自定义类,可以使用LINQ来选择值,这就是为什么我会在这里的原因。

我想减少值的重复,使其更易于管理。类似于微型关系数据库,用于保存不同的值以及属于它们的文档。

我的问题是:是否有更好的方法来处理这个问题而不使用switch语句?并且基于我所需的内容,是否有更好的问题名称?

5个回答

3
您可以按照以下方式使用字典:
    public  class ElementName
    {
        public string AccountName { get; set; }
        public string CampaignName { get; set; }
        public string DocumentName { get; set; }
        public string DestinationName { get; set; }
    }
        var animalNameDict = new Dictionary<string, ElementName>
            {
                {
                    "cow",
                    new ElementName
                        {
                            AccountName = "Farm Animals",
                            CampaignName = "Quadrupeds",
                            DocumentName = "Milk Givers",
                            DestinationName = "Milking line"
                        }
                }
            };
        ElementName elem = null;
        animalNameDict.TryGetValue("cow", out elem);

        var item = animalNameDict.FirstOrDefault(x => x.Key == "cow");

或者您可以将其转换为类的列表并使用LINQ扩展ToLookup。

除了需要与我的 switch 语句一样多的值引用之外,这是一个很好的建议。不过使用字典绝对是正确的选择。 - Logarr

2

好的,所以每个参数都是与每个动物相关的一对多关系。我的解决方案是为每个参数创建字典,类型为Dictionary<string, List<string>>,如下所示:

var accountNames = new Dictionary<string, List<string>>
    {
        {"Farm Animals", new List<string> {"Cow", "Chicken", "Turkey", "Dog", "Pig"}}
    };

那么您可以像这样使用它(此示例使用匿名类型)。您可能希望编写一个扩展方法来获取值,以清理代码并使其不区分大小写。

foreach(var animal in animals)
{
    var item = new
        {
            AccountName = accountNames.First(x => x.Value.Contains(animal)).Key
        };
}

这个完美地运作。不需要重复参数,而且每只动物最多只会使用四次。 - Logarr

1
你可以考虑使用反射来使用工厂创建动物:
namespace mynamespace
{
    public class FarmAnimal
    {
        public string accountName = "Farm Animals";
    }
    public class Quadruped : FarmAnimal
    {
        public string campaignName = "Quadrupeds";
    }
    public class Dog : Quadruped
    {
        public string documentName = "Best Friend";
        public string destinationName = "Front Porch";

        public override string ToString()
        {
            return String.Format("{0} : {1} : {2} : {3}", accountName, campaignName, documentName, destinationName);
        }
    }

    public class AnimalFactory
    {
        public static FarmAnimal create(string fileName)
        {
            try {
                ObjectHandle h = Activator.CreateInstance(null, "mynamespace." + fileName);
                return  (FarmAnimal)h.Unwrap();
            }
            catch (Exception) {
                return null;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            FarmAnimal a = AnimalFactory.create("Dog");
            Console.WriteLine(a);
        }
    }
}

1

没有办法减少代码行数,因为不知道要选择哪个accountNamecampaignName,除非在某个地方进行连接。可以像TYY建议的那样设置字典,但每个文件(类型?)仍需要四个赋值。

无论如何,我建议至少将常见字符串,例如"Farm Animals""Quadrupeds",定义为常量,以减少打字错误的机会,并使其更容易更改(如果需要)。


1
我一定会将各种名称放入资源中,创建一个一站式的位置,以更改任何值。 - Logarr
1
我距离能够点赞还差几个声望值,否则Jim会再得到一个。我考虑为每个AccountName列出文件清单,但找到正确的文件的好方法想不出来。另外,我没意识到可以像那样初始化List<T>...真高级。 - Cemafor

0
一种方法是使用工厂原型。这样,您可以将此代码委托给另一个项目并进行任何想要的操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接