简体   繁体   中英

How to make class generic to pass dynamic property class in c#

I have demo code which ignores the Extra property. I need to make this class generic.

public class HelloFriend 
{
    public static void Main(string[] args)
    {
        var s = new StringBuilder();
        s.Append("Id,Name\r\n");
        s.Append("1,one\r\n");
        s.Append("2,two\r\n");
        using (var reader = new StringReader(s.ToString()))
        using (var csv = new CsvReader(reader))
        {
            csv.Configuration.RegisterClassMap<TestMap>();
            csv.GetRecords<Test>().ToList();
        }
    }
}

public class Test : Test1
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public abstract class Test1
{
    public decimal Extra { get; set; }
}

public class TestMap : CsvClassMap<Test>
{
    public TestMap()
    {
        AutoMap();
        Map(m => m.Extra).Ignore();
    }
}

As shown in above code if I need to use different Test1 , or Test2 instead of Test, then I need to write another TestMap class. How can I avoid this? How can I make this class generic, so I can pass multiple classes like Test to ignore the Extra property?

class CsvClassMap<T> where T:Test1,class 
{
    //your class logic
}

Do you mean somehting like this?

class Program
{
    public static void Main(string[] args)
    {
        var s = new StringBuilder();
        s.Append("Id,Name\r\n");
        s.Append("1,one\r\n");
        s.Append("2,two\r\n");
        using (var reader = new StringReader(s.ToString()))
        using (var csv = new CsvReader(reader))
        {
            csv.Configuration.RegisterClassMap<TestMap<Test>>();
            csv.GetRecords<Test>().ToList();
        }
    }
}
public class Test : Test1
{
    public int Id { get; set; }
    public string Name { get; set; }

}

public Abstract class Test1 
{
   public decimal Extra { get; set; }
}


public class Test2 : Test1
{
    //other propertys
}


public class TestMap<T> : CsvClassMap<T> where T : Test1
{
    public TestMap()
    {
        AutoMap();

            Map(m => m.Extra).Ignore();

    }
}

Ok, it might work and help you for a while as long as you do not add more properties or your class interface stays stable.

Besides, i'd suggest to reinforce your implementation by adding custom attribute and using reflection to detect which properties to ignore. Here is some code to give you an idea:

public class ToBeIgnoredAttribute:Attribute
{

}

public class Test
{
    public int Property1 { get; set; }

    [ToBeIgnored]
    public int Property2 { get; set; }

}
var type= typeof(Test)// or typeof(T);
type.GetProperties().ForEach(prop =>
{

            if (prop.GetCustomAttribute<ToBeIgnoredAttribute>() != null)
            {
              Console.WriteLine($"//Call Map with right overload e.g with property name string {prop.Name}"); 
            }
            else
            {
                Console.WriteLine($"{prop.Name} is not ignored");
            }
        });

Instead of using AutoMap , only map the properties you want to be mapped.

public class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
    }
}

Another option is to add an attribute to the property.

public abstract class Test1
{
    [Ignore]
    public decimal Extra { get; set; }
}

public class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        AutoMap();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM