Tiger
Tiger

Reputation: 59

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?

Upvotes: 4

Views: 1555

Answers (4)

Darem
Darem

Reputation: 1739

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

    }
}

Upvotes: 0

Josh Close
Josh Close

Reputation: 23383

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();
    }
}

Upvotes: 0

Yves Israel
Yves Israel

Reputation: 408

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

Upvotes: 0

Yves Israel
Yves Israel

Reputation: 408

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

Upvotes: 1

Related Questions