2

Storing the generic class T in a variable and reusing it in sub methode.

For a WebService with crud on few object:

Foo:        Bar:        Etc..
SetFoo      SetBar      SetEtc
GetFoo      GetBar      GetEtc
UpdateFoo   UpdateBar   UpdateEtc
DeleteFoo   DeleteBar   DeleteEtc
GetList     ..          ..
GetPending  ..          ..
Processed   ..          ..

I have the following singleton generic wrapper on client side, with methode like:

public bool Get<T>(int i, out DloExtention result)
// DloExtention is an interface implemented by foo, bar, etc..
{
    result = null;
    try
    {
        if (typeof(T) == typeof(Foo))
        {
            result = WebserviceClient.GetFoo(i);
        }
        else if (typeof(T) == typeof(Bar))
        {
            result = WebserviceClient.GetBar(i);
        }
        else if (typeof(T) == typeof(Etc))
        {
            result = WebserviceClient.GetEtc(i);
        }
        else
        {
            throw new NotSupportedException("Get<T>, T is not a supported type.");
        }
    }
    catch (Exception ex)
    {
        Log4N.Logger.Error($"Error in Namespace.ClientSide.Get<{nameof(T)}>(int {i} ). " + ex.Message);
        return false;
    }
    return true;
}

So I can handle all the type simply with the same generic object:

class Processor
{
    HashSet<int> validOperation = new HashSet<int>();
    HashSet<int> invalidOperation = new HashSet<int>();

    internal void Run<T>()
    {
        if (Wrapper.Instance.GetListPending<T>(out int[] newEntityList) && newEntityList.Any())
        {
            ProcessEntities<T>(newEntityList, false);
        }
    }

    private void ProcessEntities<T>(int[] idsEnt, bool singleMode)
    {
        foreach (var idEnt in idsEnt)
        {
            ProcessEntity<T>(idEnt, false);
        }

        CloseValidOperation();
        RemoveInvalidOperation();
    }

    internal void ProcessIncident<T>(int idEnt)
    {
        if (Wrapper.Instance.Get<T>(idEnt, out LanDataExchangeCore.LanDataExchangeWCF.DloExtention currentEntity))
        {
            if (currentEntity.isValid() && currentEntity.toLocalDB())
            {
                validOperation.Add(idEnt);
            }
            else
            {
                invalidOperation.Add(idEnt);
            }
        }
    }

Only Wrapper.Instance.Get<T> and Wrapper.Instance.GetListPending<T> needs the generic parameter. But every methode in the way need to use it only to be able to deliver <T> to the last methode.

Is there a way to save the <T> in the Run<T> call into a private variable so inner methode of the class can use it ?

I have try adding a Type myType; but can't find the way to use it in generic call. Exemple for the Wrapper.Instance.Get<T>

Type myType; // class property

var fooWrapperGet = typeof(Wrapper).GetMethod("Get");
var fooOfMyTypeMethod = fooWrapperGet.MakeGenericMethod(new[] { myType });
//fooOfMyTypeMethod.Invoke(Wrapper.Instance , new object[] { new myType() });

// fooWrapperGet, as my wrapper is a singleton, Wrapper dont exposed Get<T>, but Wrapper.instance will expose it. 
// new myType()  <- do not compile. 
Community
  • 1
  • 1
Drag and Drop
  • 2,672
  • 3
  • 25
  • 37
  • 3
    Why don't you make your class generic (instead of your methods) if you need the same Type in different functions? – Freggar Jun 22 '18 at 08:37
  • @Freggar, well because in my head the same instance of the class was going to process for different type, like `myObj.Run(); myObj.Run(); myObj.Run();`. But yeah I could simply do that. – Drag and Drop Jun 22 '18 at 08:40
  • 1
    I really hate Fridday. @Freggar you choose how you get your gratification: either you post an answer, or you think it's a silly unhelpful x/y and I remove it. – Drag and Drop Jun 22 '18 at 08:41
  • I'd rather have you accepting the answer from @Enigmativity as he answers your actual question. My suggestion would require you to restructure your code pretty much entirely, so I don't think an answer would do justice to the question. – Freggar Jun 22 '18 at 09:16

1 Answers1

3

Does this work for you?

private Dictionary<Type, Func<int, DloExtention>> gets =
    new Dictionary<System.Type, Func<int, DloExtention>>()
    {
        { typeof(Foo), WebserviceClient.GetFoo },
        { typeof(Bar), WebserviceClient.GetBar },
        { typeof(Etc), WebserviceClient.GetEtc },
    };

public bool Get<T>(int i, out DloExtention result)
{
    result = null;
    var flag = false;
    if (gets.ContainsKey(typeof(T)))
    {
        result = gets[typeof(T)](i);
        flag = true;
    }
    return flag;
}

The beauty of this is that you can populate your dictionary at run-time.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • 2
    Ps the fun fact is that my last code in the question is from an [answer](https://stackoverflow.com/a/3958029/6560478) of yours – Drag and Drop Jun 22 '18 at 09:00