Reputation: 1161
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
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
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
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
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