Mam problem. Tzn. miałem, rozwiązałem go, ale wydaje mi się to mało fajne. Dochodzę do wniosku, że albo mam skopany projekt aplikacji, albo powinienem użyć jakiegoś wzorca, albo nie wiem sam. ;P
Chodzi o to, że potrzebuję metody, która dla danego obiektu z Modelu zwróci mi obiekt GUI, wcześniej wywołując na nim metodę.
Mój model wygląda tak:
abstract class BaseData
{
public string Name { get; set; }
}
class StringData : BaseData
{
public string MyString { get; set; }
}
class IntData : BaseData
{
public int MyInt { get; set; }
}
interface IGui<T> where T : BaseData
{
T MyData { get; }
void Initialize(T item);
}
Natomiast kod klas GUI tak:
class StringGui : BaseGui, IGui<StringData>
{
private StringData data;
#region IGui<StringData> Members
public StringData MyData
{
get { return this.data; }
}
public void Initialize(StringData item)
{
base.Initialize(item);
this.data = item;
}
#endregion
public override string ToString()
{
return string.Format("Name: {0} MyString: {1}", this.Name, this.MyData.MyString);
}
}
class IntGui : BaseGui, IGui<IntData>
{
private IntData data;
#region IGui<IntData> Members
public IntData MyData
{
get { return this.data; }
}
public void Initialize(IntData item)
{
base.Initialize(item);
this.data = item;
}
#endregion
public override string ToString()
{
return string.Format("Name: {0} MyInt: {1}", this.Name, this.MyData.MyInt);
}
}
class BaseGui
{
public string Name { get; private set; }
protected void Initialize(BaseData key)
{
this.Name = key.Name;
}
}
No i teraz moja metoda - najprostsze rozwiązanie, to if...else:
static BaseGui Create(BaseData key)
{
Type kt = key.GetType();
if (kt == typeof(StringData))
{
var val = new StringGui();
val.Initialize(key as StringData);
return val;
}
else if (kt == typeof(IntData))
{
var val = new IntGui();
val.Initialize(key as IntData);
return val;
}
return null;
}
Skuteczne, ale długie i nie DRY.
Wpadłem zatem na pomysł użycia słownika par typ-typ:
static BaseGui Create2(BaseData key)
{
Dictionary<Type, Type> dict = new Dictionary<Type, Type>()
{
{typeof(StringData), typeof(StringGui)},
{typeof(IntData), typeof(IntGui)},
};
Type keyType = key.GetType();
if (dict.ContainsKey(keyType))
{
var guiType = dict[keyType];
var val = (BaseGui)Activator.CreateInstance(guiType);
guiType.GetMethod("Initialize").Invoke(val, new object[] { key });
return val;
}
return null;
}
Oczywiście słownik powinien być poza metodą, ale nie o to chodzi teraz.
Nazwę metody "Initialize" mogę wydobyć przez refleksję, nie muszę jej hardcodować. Ale tak czy siak, wydaje mi się to trochę przekombinowane.
Ma ktoś jakiś pomysł/opinię?