0
    if (ftpType == "YouTube")
    {
        var digitalServiceResponse = JsonConvert.DeserializeObject<YoutubeMetadataResponse>(metadataJson);

        var fileRequest = new AddDeliveryFileRequest
        {
            //some code
        };

        ftpDeliveryQueue.AddFile(fileRequest);
    }
    else if (ftpType == "Flashtalking")
    {
        var metadata = JsonConvert.DeserializeObject<FlashtalkingMetadataResponse>(metadataJson);

        foreach (var file in metadata.FileList)
        {
            var fileRequest = new AddDeliveryFileRequest
            {
                //some code
            };

            ftpDeliveryQueue.AddFile(fileRequest);
        }
    }
    else if (ftpType == "Innovid")
    {
        var metadata = JsonConvert.DeserializeObject<InnovidMetadataResponse>(metadataJson);

        foreach (var file in metadata.FileList)
        {
            var fileRequest = new AddDeliveryFileRequest
            {
                //some code
            };

            ftpDeliveryQueue.AddFile(fileRequest);
        }
    }
    else
    {
        var digitalServiceResponse = JsonConvert.DeserializeObject<SizmekMetadataResponse>(metadataJson);

        foreach (var file in digitalServiceResponse.Metadata.FileList)
        {
            var fileRequest = new AddDeliveryFileRequest
            {
                //some code
            };
            ftpDeliveryQueue.AddFile(fileRequest);
        }
    }

How do I get rid of these if and else if block with the help of factory method?

Fakhar Ahmad Rasul
  • 1,595
  • 1
  • 19
  • 37
  • 1
    [C# dictionary store action/method](https://stackoverflow.com/q/46808153) – 001 Sep 21 '21 at 12:34
  • 2 Steps: 1. There is _a lot_ of duplicate code here. Refactor that first. 2.: Then, it is easier to get the remaining code refactored to use a lookup. – Fildor Sep 21 '21 at 12:49

1 Answers1

4

You could use a Dictionary where the key is the string and the value is an Action.

For example:

static void Main( string[ ] args )
{ 
    // Obviously replace the body of these lambdas with your 
    // custom logic or have them call a private member method.
    var dict = new Dictionary<string, Action>
    {
        { "YouTube", ( ) => { Console.WriteLine( "YouTube" ); } },
        { "Flashtalking", ( ) => { Console.WriteLine( "Flashtalking" ); } },
        { "Innvoid", ( ) => { Console.WriteLine( "innvoid" ); } },
    };
    
    // This is what this would look like if you wanted to accept
    // parameters. In this case, each `Action` would have to accept
    // the same number of parameters and parameter types.
    var dict2 = new Dictionary<string, Action<int, string>>
    {
        { "YouTube", ( num, str ) => { Console.WriteLine( "YouTube" ); } },
        { "Flashtalking", ( num, str ) => { Console.WriteLine( "Flashtalking" ); } },
        { "Innvoid", ( num, str ) => { Console.WriteLine( "innvoid" ); } },
    };
    
    // If you want to pass an arbitrary number of parameters
    // and types you could pass an array of objects and just
    // cast the elements to their known types.
    var dict3 = new Dictionary<string, Action<object[ ]>>
    {
        { "YouTube", ( objects ) => { Console.WriteLine( $"YouTube: {( int )objects[ 0 ]}" ); } },
        { "Flashtalking", ( objects ) => { Console.WriteLine( $"Flashtalking: {objects[ 1 ]}" ); } },
        { "Innvoid", ( _ ) => { Console.WriteLine( "innvoid" ); } },
    };

    // Then you can use it like this.
    var key = "YouTube";
    if ( dict.ContainsKey( key ) )
        dict[ key ]( );

    // Or to pass parameters.
    if ( dict2.ContainsKey( key ) )
        dict2[ key ]( 42, "Some string" );

    // Or to pass an arbitrary number of parameters and types of
    // of parameters.
    if ( dict3.ContainsKey( key ) )
        dict3[ key ]( new object[ ] { 42, "Some string" } );

}

You would want to make your Dictionary a readonly field of the encapsulating class of course.

WBuck
  • 5,162
  • 2
  • 25
  • 36
  • I like this approach, how can I accept parameters to these actions? – Fakhar Ahmad Rasul Sep 21 '21 at 13:03
  • So, in this case, you would have to use an `Action`. That being said, each action has to take the same number and types of parameters. – WBuck Sep 21 '21 at 13:05
  • @FakharAhmadRasul You could pass an array of `objects` to the lamba and cast it to the types you want. – WBuck Sep 21 '21 at 13:10
  • @FakharAhmadRasul I've updated the answer to show you how to pass parameters to the lamda's. – WBuck Sep 21 '21 at 13:16
  • I don' t see any difference in the code volume. This code only much more confusing – Serge Sep 21 '21 at 15:14
  • @Serge he wanted a way to rid himself of all the conditionals. This accomplishes that task. The "code volume" comes from me showing different ways he can use the `Dictionary` to pass parameters to the `delegate`. Currently a majority of the code would be what makes up the body of the `Action`. That obviously cannot be removed, but could be refactored in to their own `private` methods. – WBuck Sep 21 '21 at 15:18
  • @Serge also, what's confusing about using a `delegate`? Their usage is ubiquitous in most code bases these days. – WBuck Sep 21 '21 at 15:21
  • @Wbuck The code could be make shorter using generics, but I don't see much sense to do this. Perfect is the enemy of good.Pluses will be equal minuses. – Serge Sep 21 '21 at 15:26
  • @WBuck All these generic algorithms are only good in the beginning. After this customer ask to add some more functionality to this and change that and so on. Usually In the end there is nothing to be reused. – Serge Sep 21 '21 at 15:37