Best way to share Automapper Resolver

650 Views Asked by At

I have a viewmodel set up that contains several physical path strings that point to files on a server. I have virtual directories pointing to the root folders on the server. What I need to do is change this physical paths into paths that reference the virtual folders, so I can create hyper links in my page views.

What I am hoping to do is have a common resolver that I can pass a key to, then have it return the path that I need. Here is how I did it. I just want to see if there is a more simple "cleaner" way of doing it. I have only been working with mvc and c# for a couple of months, so I am still learning.

Thank in advance.

Here is the mapper info

        Mapper.CreateMap<FAG_DETAIL, OrderFagDetail>()
            .ForMember(dest => dest.TXT01, opt => opt.ResolveUsing<DrawingPathCorrect>())
            .ForMember(dest => dest.TXT02, opt => opt.ResolveUsing<Prog1PathCorrect>())
            .ForMember(dest => dest.TXT03, opt => opt.ResolveUsing<Prog2PathCorrect>())
            .ForMember(dest => dest.TXT04, opt => opt.ResolveUsing<Prog3PathCorrect>())
            .ForMember(dest => dest.TXT05, opt => opt.ResolveUsing<Prog4PathCorrect>())
            .ForMember(dest => dest.TXT07, opt => opt.ResolveUsing<Procs1PathCorrect>())
            .ForMember(dest => dest.TXT08, opt => opt.ResolveUsing<Procs2PathCorrect>())
            .ForMember(dest => dest.TXT09, opt => opt.ResolveUsing<Procs3PathCorrect>())
            .ForMember(dest => dest.TXT10, opt => opt.ResolveUsing<Procs4PathCorrect>())
            .ForMember(dest => dest.TXT11, opt => opt.ResolveUsing<FASPathCorrect>())
            .ForMember(dest => dest.TXT06, opt => opt.ResolveUsing<SecondDrawingPathCorrect>());

Here is ModelView along with the resolver that I am currently using. The model FAG_DETAIL that is the soruce for OrderfagDetail is very large so I will not included it here. It is safe to assume that in the source there are properties that match the ModelView properties exactly.

public class OrderFagDetail
{
    public decimal NO { get; set; }
    public decimal FKNO { get; set; }
    public decimal TYP { get; set; }
    public string TXT01 { get; set; } //drawing link
    public string TXT02 { get; set; } //First Op program or L20 Program
    public string TXT03 { get; set; } //Second op program or K16 Program
    public string TXT04 { get; set; } //Third op Program
    public string TXT05 { get; set; } //Fourth op Program
    public string TXT06 { get; set; } //Second drawing
    public string TXT07 { get; set; } //First Op process sheet
    public string TXT08 { get; set; } //Second Op process sheet
    public string TXT09 { get; set; } //Third Op process sheet
    public string TXT10 { get; set; } //Fourth Op process sheet
    public string TXT11 { get; set; } //First Article link

}

public interface IValueResolver
{
    ResolutionResult Resolve(ResolutionResult source);
}

public class SecondDrawingPathCorrect : ValueResolver<FAG_DETAIL, string>
{
    protected override string ResolveCore(FAG_DETAIL detail)
    {  
        PathResolver pr = new PathResolver();
        return (pr.ResolvePath(detail.TXT06,"PDFs\\"));
    }
}
public class PathResolver
{   
 public string ResolvePath(string strSrc, string strKey)
   {
       string corrected = "";
        if (strSrc.Length > 0)
        {                
            string inputdetail = strSrc;
            corrected = inputdetail.Substring(inputdetail.IndexOf(strKey)+strKey.Length, inputdetail.Length - inputdetail.IndexOf(strKey)-strKey.Length);
        }

        return (corrected);
   }

}

2

There are 2 best solutions below

3
On

Assuming that you have multiple CreateMaps like this:

Mapper.CreateMap<PdfFileObject, MyViewModel>()
    .ForMember( d => d.Uri, opt => opt.ResolveUsing(something with "pdfs")
Mapper.CreateMap<ImageFileObject, MyViewModel>()
    .ForMember( d => d.Uri, opt => opt.ResolveUsing(something with "images")
..etc

Create your resolver like this:

public class SecondDrawingPathCorrect<TFILE> : ValueResolver<FAG_DETAIL, string>
where TFILE : FAG_DETAIL
{
    private readonly string _replaceKey;
    public SecondDrawingPathCorrect(string replaceKey)
    {
        _replaceKey = replaceKey;
    }

    protected override string ResolveCore(FAG_DETAIL detail)
    {   
        string corrected = "";
        if (detail.TXT06.Length > 0)
        {                
            string inputdetail = detail.TXT06;
            corrected = inputdetail.Substring(inputdetail.IndexOf(_replaceKey) + 5, inputdetail.Length - inputdetail.IndexOf("_replaceKey) - 5);
        }

        return corrected;
    }
}

Register your maps like this:

Mapper.CreateMap<PdfFileObject, MyViewModel>()
    .ForMember( d => d.Uri, opt => opt.ResolveUsing(new SecondDrawingPathCorrect<PdfFileObject>("PDFs");

For the above to work, your PfdFileObject, ImageFileObject, etc, should implement/inherit FAG_DETAIL.

There is another option too, if you can control FAG_DETAIL, you can expose on it a property string FilePathPrefix (which for PdfFileObject will return "PDFs"). Then you can use it in the resolver itself (i.e. in the "replace" part use detail.FilePrefix instead of _replaceKey).

With the latest one, you can drop the generic part of the resolver , and do registration like this:

Mapper.CreateMap<FAG_DETAIL, MyViewModel>()
        .ForMember( d => d.Uri, opt => opt.ResolveUsing<SecondDrawingPathCorrect>()
.Include<PdfFileObject, MyViewModel>()
.Include<ImageFileObject, MyViewModel>()
...more includes;
0
On

maybe for improvement you can make the PathResolver class static or singleton the difference is Static Class:

  1. You cannot create the instance of static class.
  2. Loaded automatically by the .NET Framework common language runtime (CLR) when the program or namespace containing the class is loaded.
  3. Static Class cannot have constructor.
  4. We cannot pass the static class to method.
  5. We cannot inherit Static class to another Static class in C#.

Singleton:

  1. You can create one instance of the object and reuse it.
  2. Singleton instance is created for the first time when the user requested.
  3. Singleton class can have constructor.
  4. You can create the object of singleton class and pass it to method.
  5. Singleton class does not say any restriction of Inheritance.
  6. We can dispose the objects of a singleton class but not of static class.