Catel/Catel — pull request #3 by jdehaan (2013-06-20 12:43:28+00:00)
Title: Added support for KnownTypeAttribute with method name instead of a type

Use case when the KnownType's need to be determined at runtime in a plugin based environment.

Sample code reproducing the issue (for unpatched code) that is solved with this change:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using Catel.Data;

namespace SmallTest
{

public interface IParams
{

}

// Setting the known types on a base class (not interface) solves the issue
// but is not feasible as the possible derived classes are implemented by
// plugins which are not known in advance. Is there a way to do this dynamically,
// by making a request to the plugin manager?
//[KnownType(typeof(ParamsPluginA))]
//[KnownType(typeof(ParamsPluginB))]
[KnownType("KnownTypes")]
public class ParamsBase : SavableModelBase, IParams
{

// This method returns the array of known types.
static Type[] KnownTypes()
{
return new Type[] { typeof(ParamsPluginA), typeof(ParamsPluginB) };
}
}

[Serializable]
public class ParamsPluginA : ParamsBase
{
#region Property: SettingA
public String SettingA
{
get { return GetValue(SettingAProperty); }
set { SetValue(SettingAProperty, value); }
}

public static readonly PropertyData SettingAProperty =
RegisterProperty("SettingA", typeof(String));
#endregion
}

[Serializable]
public class ParamsPluginB : ParamsBase
{
#region Property: SettingB
public String SettingB
{
get { return GetValue(SettingBProperty); }
set { SetValue(SettingBProperty, value); }
}

public static readonly PropertyData SettingBProperty =
RegisterProperty("SettingB", typeof(String));
#endregion
}

public class Container : SavableModelBase
{
#region Property: Parameters
public ObservableCollection Parameters
{
get { return GetValue>(ParametersProperty); }
set { SetValue(ParametersProperty, value); }
}

public static readonly PropertyData ParametersProperty =
RegisterProperty("Parameters", typeof(ObservableCollection),
new ObservableCollection());
#endregion
}

class Program
{

static void Main(string[] args)
{
var c = new Container();
var pA = new ParamsPluginA();
pA.SettingA = "TestA";
c.Parameters.Add(pA);
var pB = new ParamsPluginB();
pB.SettingB = "TestB";
c.Parameters.Add(pB);
c.Save("test.xml", SerializationMode.Xml);
var c2 = Container.Load("test.xml", SerializationMode.Xml);
}
}
}