Server side:
Service details:
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
[ServiceContract]
public interface IAppConfigurationManager
{
[OperationContract]
object ChangeObjectProperty(object myCustomObject);
}
Implementation:
public class AppConfigurationManager : IAppConfigurationManager
{
public object ChangeObjectProperty(object myCustomObject)
{
foreach (Type type in Globals.MyCustomTypes)
{
if (type == myCustomObject.GetType())
{
foreach (PropertyInfo Property in myCustomObject.GetType().GetProperties())
{
if(Property.Name == "ID")
{
int oldValue = Convert.ToInt32(Property.GetValue(myCustomObject));
Property.SetValue(myCustomObject, oldValue + 1);
break;
};
};
}
}
return myCustomObject;
}
}
Helper class is used for collecting of KnownTypes:
public static class Helper
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
Globals.MyCustomTypes = new List<Type>();
System.Collections.Generic.List<System.Type> knownTypes =
new System.Collections.Generic.List<System.Type>();
Assembly assembly = Assembly.LoadFrom(@"D:\WCF\RuntimeManagement\bin\Debug\RuntimeManagement.dll");
foreach (Type type in assembly.GetTypes())
{
if (type.Name.Contains("Customer") || type.Name.Contains("Account"))
{
knownTypes.Add(type);
Globals.MyCustomTypes.Add(type);
};
};
return knownTypes;
}
}
Classes:
[DataContract]
public class Customer
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
}
[DataContract]
public class Account
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public Customer AccountOwner { get; set; }
}
Client side:
Before invoking the service, trying to register KnownTypes at client side also:
private void fmMain_Load(object sender, EventArgs e)
{
MyCustomTypes = new List<Type>();
Assembly assembly = Assembly.LoadFrom(@"D:\WCF\RuntimeManagement\bin\Debug\RuntimeManagement.dll");
foreach (Type type in assembly.GetTypes())
{
if (type.Name.Contains("Customer") || type.Name.Contains("Account"))
{
MyCustomTypes.Add(type);
if (type.Name == "Customer")
{
CustomerType = type;
};
foreach (var operation in Globals.AppConfigMgrClient.Endpoint.Contract.Operations)
{
operation.KnownTypes.Add(type);
};
};
};
object myCustomerObject = Activator.CreateInstance(CustomerType);
foreach (PropertyInfo Property in myCustomerObject.GetType().GetProperties())
{
if (Property.Name == "ID")
{
Property.SetValue(myCustomerObject, 111);
break;
};
};
myCustomerObject = Globals.AppConfigMgrClient.ChangeObjectProperty(myCustomerObject);
foreach (PropertyInfo Property in myCustomerObject.GetType().GetProperties())
{
if (Property.Name == "ID")
{
Debug.WriteLine(Property.GetValue(myCustomerObject).ToString());
break;
};
};
}
Got error here:
myCustomerObject = Globals.AppConfigMgrClient.ChangeObjectProperty((RuntimeManagement.CatalogManagement.Customer)myCustomerObject);
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:myCustomObject. The InnerException message was 'Element 'http://tempuri.org/:myCustomObject' contains data from a type that maps to the name 'http://tempuri.org/:Customer'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'Customer' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
May be long post, hope you got idea what I am trying to do here:
- Adding
Customer
andAccount
classes toServiceKnownType
at server side helper class. - On load event of client side, trying to register
KnownTypes
from the same assembly whereCustomer
andAccount
exists. - Then creating instance of
Customer
type, set it'sID
property to 111, send itOperationContract
calledChangeObjectProperty
. After successful execution, it should increment ID.
Thanks for your time.