I think you need some means of binding a component to the type of data it accepts. Otherwise, how do you know they match up (other than by parsing the name and using your human intuition, which a computer can't do)?
This can be done with generics and inheritance, like this:
abstract class MyComponentData
{
abstract public string ElementComponentType { get; }
}
class MyComponentData1 : MyComponentData
{
override public string ElementComponentType { get { return "Type1"; } }
}
class MyComponentData2 : MyComponentData
{
override public string ElementComponentType { get { return "Type2"; } }
}
abstract class MyComponentClass
{
}
class MyComponentClass<T> : MyComponentClass where T: MyComponentData
{
public void AcceptData(T input)
{
//Do something with the data
}
}
With this scheme, it is required to declare what type of data a particular component will accept as part of the declaration of the generic class MyComponentClass. So if you have a component that can handle MyComponentData1, you have to declare it as var c = new MyComponentClass<MyComponentData1>(). Thus any instance of a component is bound to a specific data type.
To initialize your lookup list:
Dictionary<string, MyComponentClass> _userInterfaceElements = new Dictionary<string, MyComponentClass>();
_userInterfaceElements.Add("Type1", new MyComponentClass<MyComponentData1>());
_userInterfaceElements.Add("Type2", new MyComponentClass<MyComponentData2>());
And to dispatch an incoming request for a component, passing the data, using the table:
static void TransferUIDataToComponent<T>(T data) where T: MyComponentData
{
MyComponentClass<T> c = _userInterfaceElements[data.ElementComponentType] as MyComponentClass<T>;
c.AcceptData(data);
}
But... hey.... we don't actually need the table any more! So you can just do this:
static void TransferUIDataToComponent<T>(T data) where T: MyComponentData
{
var c = new MyComponentClass<T>();
c.AcceptData(data);
}
Meaning you can get rid of _userInterfaceElements, get rid of ElementComponentType, and get rid of the abstract MyComponentClass that I added (we only needed it for _userInterfaceElements so we could store any component). And notice we have completely removed the need for any cast.
Then, to call the dispatch:
var data1 = new MyComponentData1();
TransferUIDataToComponent<MyComponentData1>(data1);
var data2 = new MyComponentData2();
TransferUIDataToComponent<MyComponentData2>(data2);