Kixoka
Kixoka

Reputation: 1161

Returning data with different types from a single method

I am trying to find a way to simplify some code where I want to get data with different structures from one method.

I have the following code:

public class VmOne
{
    private ObservableCollection<Structure1> GetFirstStructCollection()
    {
        var myList = new List<Structure1>();
        myList.Add(new Structure1
        {
            Id = 1,
            Name = "John Doe",
            Description = "struct 1 test"
        });

        myList.Add(new Structure1
        {
            Id = 2,
            Name = "Sally Doe",
            Description = "struct 1 test"
        });

        return new ObservableCollection<Structure1>(myList);
    }

    private ObservableCollection<Structure2> GetSecondStructCollection()
    {
        var myList = new List<Structure2>();
        myList.Add(new Structure2
        {
            Id = 1,
            Name = "Saphire Doe",
            Description = "struct 2 test"
        });

        myList.Add(new Structure2
        {
            Id = 2,
            Name = "Onyx Doe",
            Description = "struct 2 test"
        });

        return new ObservableCollection<Structure1>(myList);
    }

    // this wont work....
    public ObservableCollection<object> GetDataByIndex(int pIndex)
    {
        ObservableCollection<object> data;

        if (pIndex == 1)
        {
            data = GetFirstStructCollection();      
        }

        if (pIndex == 2)
        {
            data = GetSecondStructCollection();
        }
        return data;
    }
}

Which is called by

public class MyMain
{

    public void DoSomething()
    {
        var job = new VmOne();

        var data = job.GetDataByIndex(1);

        // .... do something useful with the data
    }
}

I have not been able to figure out a way to do this. Can this be done? Just need a little direction.

The use of the data is as follows, the user selects a discipline that they wish to maintain. Each discipline can have 2 or more data tables associated to it. They can step through the data tables to perform maintenance. Each table has their own unique structure. I want to use a common UI so that they only need to select a discipline which will load the appropriate tables to be maintained.

In order to do this I have the table names in an array and when they select from the drop down the index will point to the array which has a table name. I then want to call my method using either an index or the table name to return back the collection of data. Since this is a WPF app the data is returned in an ObservableCollection .

So the method would return any combination of ObservableColleciton types....

Upvotes: 0

Views: 117

Answers (4)

Arie
Arie

Reputation: 5373

You can do something similar to what you want using generics:

class Zoo
    {
        public ObservableCollection<T> GetData<T>() where T : class
        {
        if (typeof(T) == typeof(Cat))
            return new ObservableCollection<T>(this.GetCatCollection().Cast<T>().ToList());
            // or:
            // return new ObservableCollection<T>(Cat.GetDefaultCollection().Cast<T>().ToList());

        if (typeof(T) == typeof(Dog))
            return new ObservableCollection<T>(Dog.GetDefaultCollection().Cast<T>().ToList());

        if (typeof(T) == typeof(Lion))
            return new ObservableCollection<T>(Lion.GetDefaultCollection().Cast<T>().ToList());

        return null;

        // pseudo-switch version
        //ObservableCollection<T> result = null;

        //var @switch = new Dictionary<Type, Action> {
        //{ typeof(Cat), () => result = new ObservableCollection<T>(Cat.GetDefaultCollection().Cast<T>().ToList()) },
        //{ typeof(Dog), () => result =  new ObservableCollection<T>(Dog.GetDefaultCollection().Cast<T>().ToList())},
        //{ typeof(Lion), () => result = new ObservableCollection<T>(Lion.GetDefaultCollection().Cast<T>().ToList())}};

        //@switch[typeof(T)]();

        //return result;
    }

    private ObservableCollection<Cat> GetCatCollection()
    {
            ObservableCollection<Cat> list = new ObservableCollection<Cat>();
            list.Add(new Cat { CatName = "Cat No. 1" });
            list.Add(new Cat { CatName = "Cat No. 2" });
            list.Add(new Cat { CatName = "Cat No. 3" });
            return list;
    }

}

class Cat
{
    public string CatName { get; set; }

    public static ObservableCollection<Cat> GetDefaultCollection()
    {
        ObservableCollection<Cat> list = new ObservableCollection<Cat>();
        list.Add(new Cat { CatName = "Cat No. 1" });
        list.Add(new Cat { CatName = "Cat No. 2" });
        list.Add(new Cat { CatName = "Cat No. 3" });
        return list;
    }
}

class Dog
{
    public string DogName { get; set; }

    public static ObservableCollection<Dog> GetDefaultCollection()
    {
        ObservableCollection<Dog> list = new ObservableCollection<Dog>();
        list.Add(new Dog { DogName = "Dog No. 1" });
        list.Add(new Dog { DogName = "Dog No. 2" });
        list.Add(new Dog { DogName = "Dog No. 3" });
        return list;
    }
}
class Lion
{
    public string LionName { get; set; }

    public static ObservableCollection<Lion> GetDefaultCollection()
    {
        ObservableCollection<Lion> list = new ObservableCollection<Lion>();
        list.Add(new Lion { LionName = "Lion No. 1" });
        list.Add(new Lion { LionName = "Lion No. 2" });
        list.Add(new Lion { LionName = "Lion No. 3" });
        return list;
    }
}

Example use:

    var zoo = new Zoo();

    ObservableCollection<Cat> cats = zoo.GetData<Cat>();
    ObservableCollection<Dog> dogs = zoo.GetData<Dog>();
    ObservableCollection<Lion> lions = zoo.GetData<Lion>();


    Console.WriteLine("-------------- Cats:");
    cats.ToList().ForEach(cat => Console.WriteLine(cat.CatName));
    Console.WriteLine("-------------- Dogs:");
    dogs.ToList().ForEach(dog => Console.WriteLine(dog.DogName));
    Console.WriteLine("-------------- Lions:");
    lions.ToList().ForEach(lion => Console.WriteLine(lion.LionName));

result:

-------------- Cats:
Cat No. 1
Cat No. 2
Cat No. 3
-------------- Dogs:
Dog No. 1
Dog No. 2
Dog No. 3
-------------- Lions:
Lion No. 1
Lion No. 2
Lion No. 3

Upvotes: 0

Alexander Leyva Caro
Alexander Leyva Caro

Reputation: 1253

Are you here about varianza? ObservableCollection<T> are not co-vantiant, this mean that you can pass an ObservableCollection<Tk> where Tk are inherit from T. Notice that you can do this with arrays.

object[] data1 = new Structure1[0];  // is valid becuase array are covariant
ObservableCollection<Structure> data2 = new ObservableCollection<Structure1>();  // compilation error becuase ObservableCollection are not covariant

You can use arrays and the create the ObservableCollection<object> like this:

private Structure1[] GetFirstStructCollection()
    {
        return new[]
        {
            new Structure1
            {
                Id = 1,
                Name = "John Doe",
                Description = "struct 1 test"
            },
            new Structure1
            {
                Id = 2,
                Name = "Sally Doe",
                Description = "struct 1 test"
            }
        };
    }

    private Structure2[] GetSecondStructCollection()
    {
        return new[]
        {
            new Structure2
            {
                Id = 1,
            Name = "Saphire Doe",
            Description = "struct 2 test"
            },
            new Structure2
            {
                Id = 2,
            Name = "Onyx Doe",
            Description = "struct 2 test"
            }
        };
    }

        public ObservableCollection<object> GetDataByIndex2(int pIndex)
        {
            ObservableCollection<object> data = null;
            if (pIndex == 1)
            {
                data = new ObservableCollection<object>(GetFirstStructCollection());
            }

            if (pIndex == 2)
            {
                data = new ObservableCollection<object>(GetSecondStructCollection());
            }
            return data;
        }

Upvotes: 0

barca_d
barca_d

Reputation: 1050

You could maybe try something along these lines, although your specifications are vague and a bit unclear:

void Main()
{
   // call it
   VmOne vmOne = new VmOne();
   vmOne.GetDataByIndex<Structure1>(GetStructCollection<Structure1>());

   // ...
}

// Define other methods and classes here
public class VmOne
{
     public ObservableCollection<TStruct> GetStructCollection<TStruct>() where TStruct : class //     or base class for the structures if you can do it
    {
        var myList = new List<TStruct>();
       // add to list somehow
       return new ObservableCollection<TStruct>(myList);
     }

    public ObservableCollection<TStruct> GetDataByIndex<TStruct>(System.Action getStructCollection) where TStruct : class
    {
         ObservableCollection<TStruct> data = getStructCollection<TStruct>();   

        // ...

        return data;
     }
}

Bear in mind this is merely a sketch of what you could try to do

Upvotes: 0

swe
swe

Reputation: 1455

i think you cannot do that the way you are looking for. If you define a class(of t) (vb) oder class (c#), then you can create a method dosomething, which then gives you back a generic thing.

I would suggest to define an interface, that structure1 and structure2 do implement, and let your function return an observablecollection of your interface.

cheers

Upvotes: 2

Related Questions