0

I'm trying to use a dynamic object on a generic class. I've based myself on one of the answers of this thread, that basically suggest the usage of a dynamic type instead of reflection and, as I'd like to increase type safety, I'd rather use the dynamic type approach.

This is the class I have:

public class DataGrid<T>
{
    public List<T>? RawData;

    public void CreateInstance(T dataMessageType)
    {
        RawData = new List<T>();
    }

    public void GetHistoricalData(T dataMessageType)
    {         
        var item = GetDataFromSource(dataMessageType); // ommitted to simplify
        RawData?.Add(item);
    }
}

Which I'm trying to further use here:

public class MainGrid
{
    public void LoadData()
        {                
            dynamic t = GetDataType(); // this method returns a Type. Ommitted to simplify; 
            var historicalData = new DataGrid<t>(); // Error. See comment 1 below
            historicalData.CreateInstance(t); // Error. Comment 2 below
            historicalData.GetDataFromSource(t); // Error. Also comment 2 below
        }
}

Comment 1: I know this is incorrect, but I'm not sure how this could be done using a dynamic type as opposed to reflection.

Comment 2: when I replace 't' by the Type returned by the (ommitted) GetDataTypecode method the code compiles, but there is a runtime error informing 'The best overloaded method match for ... has some invalid arguments'. I don't see what I'm missing here too...

roccaforte
  • 81
  • 5
  • 1) your link leads to the main SO page 2) as I understand `dynamic` was specifically created as type to say "shut up compiler, there is no type-safety here" so it's interesting how you want "to increase type safety" using it) – Guru Stron Jul 19 '22 at 12:54
  • `dynamic` is a red herring here. It could be used to call a method with an object that you don't know the type of at compile time, but you don't have any objects, only a `Type`. You'll have to use the usual techniques for instantiating a generic type with that (`Activator.CreateInstance(typeof(DataGrid<>).MakeGenericType(t))`). You can then use `dynamic` to call methods on that, if you like -- although you should also consider if generics are appropriate here at all, if they don't make the implementation of `DataGrid` simpler or safer. – Jeroen Mostert Jul 19 '22 at 12:59
  • Thanks. I've just fixed the link. By 'increasing type safety using a dynamic type' I meant that I'd like to avoid the pitfalls of using string types on the MethodInfo methods (e.g. "MethodInfo method = typeof(Service).GetMethod("Process");", where I'd be vulnerable to changes in the name of 'Process'. – roccaforte Jul 19 '22 at 12:59
  • @JeroenMostert could you please give me some guidance on how to further investigate this? Sorry, I'm not sure what do you exacly mean by 'the usual techniques for instantiating a generic type', considering the Type is returned by another method and stored in a dynamic object. What I'm trying to avoid here is the usage of reflection, which I think would be the standard approach for this. – roccaforte Jul 19 '22 at 13:05
  • There is zero reason for using `dynamic` to hold a `Type`, because you know the object's type -- it's `Type`. :P `dynamic` cannot instantiate generics; the example you link calls a generic *method*, and uses `dynamic` to do type inference at runtime. This cannot work in your case, because the whole point is that you have no `DataGrid` (or any other object at all) and need to get one. – Jeroen Mostert Jul 19 '22 at 13:06
  • @JeroenMostert it happens that, if I use 'Type' instead of 'dynamic' when declaring 't', I couldn't even compile 'historicalData.CreateInstance(t)' and 'historicalData.GetDataFromSource(t)', which made me think I was going in the wrong direction. When it comes to your point on having no DataGrid at all, when I instantiate it with a new DataGrid(), the code compiles and the application runs, but I still face the errors with the two statements after that. – roccaforte Jul 19 '22 at 13:18
  • You seem to be confused about the purpose of `T` here. If `GetDataType` returns a `Type` which is intended to be used as the value of the type parameter for `DataGrid`, it cannot then also serve as a parameter to a method like `CreateInstance`, because that expects an *instance* of that type. One or the other has to change. Unfortunately your code doesn't contain enough context to say how. Currently a method like `GetHistoricalData` doesn't use the `dataMessageTypes` parameter at all; is it even necessary? – Jeroen Mostert Jul 19 '22 at 13:22

1 Answers1

0

if you want a dynamic feeling but also way more safer than the actual dynamic. you can create your own custom dynamic object . you can start with this :

public class MyObject : DynamicObject
{

    public override bool TrySetMember(SetMemberBinder binder, object? value)
    {
        return base.TrySetMember(binder, value);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object? result)
    {
        return base.TryGetMember(binder, out result);
    }
}

so you have the ability to control the Get/Set on a object. i hope this helps.

AliSalehi
  • 159
  • 1
  • 1
  • 13