开发者

Converting a C# method to use generics referencing a property inside

I would like to convert a method to use generics. It is currently hard-coded to these types:

  • DataContext.Document in the data context's partial class and inheriting from object
  • DataContext.Documents also in this partial class and inheriting from Linq.Table<Document>
  • Import.Document inheriting from a custom class ImportObject

Original method:

public void ProcessDocuments(Delegate method, params object[] args)
{
    using (DataContext dc = new DataContext())
    {
        dc.ObjectTrackingEnabled = false;

        // Map from DataContext object to ImportObject
        Mapper.CreateMap<Document, Import.Document>();

        // Loop through DataContext objects
        foreach (Document d in dc.Documents)
        {
            Import.Document doc = Mapper.Map<Document, Import.Document>(d);
            args[0] = doc;
            method.DynamicInvoke(args);
        }
    }
}

Attempted method:

public void ProcessImportObjects<TSource, TDestination>
    (Action<TDestination, ImportDataSource, int> processMethod, ImportDataSource import开发者_开发百科Source, int resultId)
{
    using (DataContext dc = new DataContext())
    {
        dc.ObjectTrackingEnabled = false;
        Mapper.CreateMap<TSource, TDestination>();

        foreach (TSource d in dc.Documents) // PROBLEM: Hard-coded reference to property on DataContext
        {
            TDestination doc = Mapper.Map<TSource, TDestination>(d);
            processMethod(doc, importSource, resultId);
        }
    }
}

(Here, TDestination should be of type ImportObject but I'm not sure how to express that.)

As shown in the comment, the foreach needs to reference a property on the DataContext that is an IEnumerable<TSource>. Does this mean I need to pass the DataContext in as a parameter or is there a better way?


It sounds like you need to parameterize the property name in DataContext. One way to do it is to pass in a function that takes a DataContext and returns your enumerable (a Func<DataContext, IEnumerable<TSource>>) and then you would pass in a lambda like dc => dc.Document as that parameter.

Another option, which would work (but without type-safety) is to pass in the property's name as a string and then use Reflection to access it.

public void ProcessImportObjects<TSource, TDestination>
    (Func<DataContext, IEnumerable<TSource>> dcProperty,
     Action<TDestination, ImportDataSource, int> processMethod,
     ImportDataSource importSource,
     int resultId)
{
    using (DataContext dc = new DataContext())
    {
        dc.ObjectTrackingEnabled = false;
        Mapper.CreateMap<TSource, TDestination>();

        foreach (TSource d in dcProperty(dc))
        {
            TDestination doc = Mapper.Map<TSource, TDestination>(d);
            processMethod(doc, importSource, resultId);
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜