Selecting values ​​for multiple properties based on a string

I am creating an automated workflow system that will have to set 4 string values ​​based on the name of the file to be read. I have a valid switch statement, but as you will see in the example, I have many common meanings between different filenames. I am looking for a way to simplify this code as I will soon have up to 40 different filenames to work with.

Each file must have the following properties assigned: AccountName, CampaignName, DocumentName, and DestinationName. Account and campaign are often used in conjunction with similar files, but the document is almost always unique. Below is an example.

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;

      

I don't know if a dictionary is what I'm looking for, or if I would create a custom class that could select values ​​using LINQ, so here I am.

I want to reduce repetition of values ​​to make it more manageable. Something like a micro-relational database for storing different values ​​and which documents belong to them.

My questions are: Is there a better way to approach this without a switch statement? And is there a better name for my question based on what I need?

+3


source to share


5 answers


OK, so each parameter is a one-to-many relationship for each animal. My solution would be to create dictionaries for each parameter with a type Dictionary<string, List<string>>

, for example:

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

      



Then you will use it in a style like this (this example uses anonymous types). You might want to create an extension method to retrieve the value to clean up your code and make it case sensitive.

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

      

+2


source


You can use a dictionary as described below: -

    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");

      



or you can include it in the list of classes and use the linq ToLookup extension.

+3


source


There is really no way to reduce the number of lines of code, because there is no way to know which accountName

or campaignName

to select without swiping something somewhere. You can customize the dictionary like TYY sentences, but it still contains four assignments for each file (type?).

Anyway, I would suggest having at least common strings like "Farm Animals"

and "Quadrupeds"

defined as constants somewhere to reduce the likelihood of os types and make it easier to change them when needed.

+1


source


You might consider using reflection to use a factory to create animals:

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


source


The approach would be to use Factory or Prototype . This way you can delegate this code to another project and do whatever you want.

0


source







All Articles