Bluecakes
Bluecakes

Reputation: 2159

C# Call method on non-generic list of generic classes

My main class Computer interacts with a number of external systems and currently has the logic for getting/updating their info crammed into it.

I want to move the logic for each system to it's own separate class and i've been able to part of the way there but i'm having trouble calling a method on them.

I've only just recently started playing around with generics so this is probably badly written code, apologies for your eyes in advance.

These are my System classes

public class System
{
    public string Name { get;set; }
}

public class System<T> : System
{
    public virtual T GetData() => default(T);
    public virtual void UpdateData() {}
}

public interface ISystem<T>
{
    T GetData();
    void UpdateData();
}       

These are the systems i've created using the System classes:

public class ComplexSystem : ISystem<RegistryKey>
{
    public string GetData() => MethodThatGetsRegistryData();
    public bool UpdateData() => MethodThatUpdatesRegistry();
}

public class IntSystem : ISystem<int>
{
    private int value = 9;
    public int GetData() => this.value;
    public void UpdateData()
    {
        this.value = 3;
    }
}

public class StringSystem : ISystem<string>
{
    private string value = "hello";
    public string GetData() => this.value;
    public void UpdateData()
    {
        this.value = "updated";
    }
}

and this is how i'm trying to use the whole thing:

public class Computer
{   
    public List<System> AssociatedSystems = new List<System>();

    public Computer()
    {
        this.AssociatedSystems.Add(new System<ComplexSystem> {Name="ComplexSystem"});
        this.AssociatedSystems.Add(new System<IntSystem> {Name="IntSystem"});
        this.AssociatedSystems.Add(new System<StringSystem> {Name="StringSystem"});
    }

    public void UpdateDataWhenComputerIsChanged()
    {           
        // is it possible to loop through them and call UpdateData on each one without know what generic they are?
        foreach (var associatedSystem in this.AssociatedSystems)
        {
            // something like...
            associatedSystem.UpdateData();
        }
    }
}

Which results in

System does not contain a definition for UpdateData() and no extension method could be found

I'm not married to the code above so if there's a better way of doing it i'm all for learning. I'm essentially looking for a way to have a list of classes that contain data logic (like GetData() and UpdateData()) so i don't have to put that logic into my main class (Computer)

Upvotes: 1

Views: 167

Answers (2)

Magnus
Magnus

Reputation: 46997

So function UpdateData does not exist in System and that is why you cant call it. I would suggest introducing an ISystem interface and put Name (if you need it) and UpdateData in that and let the generic ISystem<T> interface inherit from that.

public interface ISystem
{
    string Name {get;set;}
    void UpdateData();
}

public interface ISystem<T> : ISystem
{
    T GetData();
}

public class Computer
{
    public List<ISystem> AssociatedSystems = new List<ISystem>();
    .....
    foreach (var associatedSystem in this.AssociatedSystems)
    {
        associatedSystem.UpdateData();
    }
}

Upvotes: 2

Emad
Emad

Reputation: 3949

Yes there are multiple ways to do this. The ones that I can think of are:

  1. Type checking each System in the loop
  2. Adding a Type property to system
  3. Adding a UpdateData(object) or UpdateData(SomeHighLevelType)

If you need more help please specify the nature of your systems. Are they limited to some specific types or you want is extendable for ever and how much speed critical is your project and I can elaborate more

Upvotes: 0

Related Questions