简体   繁体   中英

Can this C# method duplication be rewritten (Lambdas? Delegates?)?

Bear with me the world of lambdas, etc is making my head hurt. I'm not even sure if the following code example is one where someone would use a lambda.

public static void AddDownloadMimeTypesToWebApps()
{
    var webApps = from svc in SPFarm.Local.Services.OfType<SPWebService>()
                  from SPWebApplication webApp in svc.WebApplications
                  where webApp.IsAdministrationWebApplication == false
                  select webApp;
    foreach (SPWebApplication webApp in webApps)
    {
        foreach (FileExtensionData fed in MimeTypes)
        {
            webApp.AllowedInlineDownloadedMimeTypes.Add(fed.MimeType);
        }
        webApp.Update();
    }
}

public static void DeleteDownloadMimeTypesFromWebApps()
{
    var webApps = from svc in SPFarm.Local.Services.OfType<SPWebService>()
                  from SPWebApplication webApp in svc.WebApplications
                  where webApp.IsAdministrationWebApplication == false
                  select webApp;
    foreach (SPWebApplication webApp in webApps)
    {
        foreach (FileExtensionData fed in MimeTypes)
        {
            webApp.AllowedInlineDownloadedMimeTypes.Remove(fed.MimeType);
        }
        webApp.Update();
    }
}

Both methods are identical except for the Add() or Remove() calls.

Is there a way to refactor these that doesn't involve some strange reflection calls with passing in method names as strings, etc?

Cheers!

Initially, I would suggest you write a method to get the webApps:

public static IEnumerable<SPWebApplication> GetWebApps()
{
    var webApps = from svc in SPFarm.Local.Services.OfType<SPWebService>()
                  from SPWebApplication webApp in svc.WebApplications
                  where webApp.IsAdministrationWebApplication == false
                  select webApp;
    return webApps;   
}

Then, despite the fact that the rest of code is quite similar, since they do different things, I wouldn't join them to one method.

public static void AddDownloadMimeTypesToWebApps(IEnumerable<SPWebApplication> webApps)
{
    foreach (var webApp in webApps)
    {
        foreach (var fed in MimeTypes)
        {
            webApp.AllowedInlineDownloadedMimeTypes.Add(fed.MimeType);
        }
        webApp.Update();
    }
}

and

public static void DeleteDownloadMimeTypesFromWebApps(IEnumerable<SPWebApplication> webApps)
{
    foreach (var webApp in webApps)
    {
        foreach (var fed in MimeTypes)
        {
            webApp.AllowedInlineDownloadedMimeTypes.Remove(fed.MimeType);
        }
        webApp.Update();
    }
}

Now you have three different methods with three different responsibilities. The first, GetWebApps , returns a sequence of the WebApps . The second adds download mime types to the web apps you pass as a parameter, AddDownloadMimeTypesToWebApps and the last one, DeleteDownloadMimeTypesFromWebApps delete them.

This way it is easy to remember what exactly does each method. Their purpose are crystal clear. Futhermore you don't hide from the consumer of the method what is needed as input. For instance, someone reads the name of the second method. The first question is which web apps? In the original code, where we don't pass the web apps as a parameter, we fetch them inside the mehtod's body. This is meaningless, since according to the name of the method we just want to add download mime types to some web apps and not to fetch them and then add the donwload mime types.

Last but not least since the retrieval of web apps is the same for both the cases of adding and deleting, we have to isolate this to one method that would serve exactly this. The last action not only enhances that mentioned above but it is also a clear appliance of the DRY principle, don't repeat yourself , which help us to write more maintainable code. Now if any time in the future you have to make some change in the retrieval of the web apps, you would have only one place, in which you have to look at, not two or more places.

How bout something like this where we can make the unique code a lambda:

private static void DownloadMimeTypesToWebApps(Action<SPWebApplication,FileExtensionData> action)
{
    var webApps = from svc in SPFarm.Local.Services.OfType<SPWebService>()
              from SPWebApplication webApp in svc.WebApplications
              where webApp.IsAdministrationWebApplication == false
              select webApp;
    foreach (SPWebApplication webApp in webApps)
    {
       foreach (FileExtensionData fed in MimeTypes)
       {
           action.Invoke(webApp,fed);
       }

       webApp.Update();
    }   

}

public static void AddDownloadMimeTypesToWebApps()
{
    DownloadMimeTypesToWebApps((webApp,fed) => webApp.AllowedInlineDownloadedMimeTypes.Add(fed.MimeType));
}

public static void DeleteDownloadMimeTypesToWebApps()
{
    DownloadMimeTypesToWebApps((webApp,fed) => webApp.AllowedInlineDownloadedMimeTypes.Remove(fed.MimeType));        
}

What about just a plain old parameter and if else?:

public static void EditMimeTypesToWebApps(int editType) // maybe you can make it an enum
{
    var webApps = from svc in SPFarm.Local.Services.OfType<SPWebService>()
                  from SPWebApplication webApp in svc.WebApplications
                  where webApp.IsAdministrationWebApplication == false
                  select webApp;
    foreach (SPWebApplication webApp in webApps)
    {
        foreach (FileExtensionData fed in MimeTypes)
        {   
            if(editType == 0)
            {
                webApp.AllowedInlineDownloadedMimeTypes.Remove(fed.MimeType);
            }
            else
            {
                webApp.AllowedInlineDownloadedMimeTypes.Add(fed.MimeType);
            }
        }
        webApp.Update();
    }
}

Easy enough to read. Easy enough for any level to maintain.

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