Accessing WCF service inside DataContract set accessors?
G'day,
I am trying to work out how (if it is even possible) to access the WCF Service object from within a set accessor for the datacontract property.
For instance:
class MyService:IMyService
{
...
public string SomeMethod(int property)
...
}
[DataContract]
class MyType
{
[DataMember]
public int MyProperty
{
...
set
{
// Use a call to the already created WCF instance inside the set accessor
_otherValue = WCFInstance.SomeMethod(value);
}
}
...
}
This is probably not best practice, but is this even possible? I can instantiate a new instance of the MyS开发者_如何学Goervice class to make the call in the above situation, but it seems a waste when there is already one in memory processing the WCF request.
Any assistance would be heaps appreciated. Any questions or more information required, please feel free to ask.
Many thanks, Steve
I had a similar problem. I need this functionality for doing a kind of "lazy" loading while the client accessing some properties. When your service client uses the ChannelFactory (from WCF) you must have a reference to the assembly that defines the SerivceContracts and the OperationContracts. Then you can easily implement the method for creating a serivce channel in the same assembly.
In the SerivceContract/DataContract assembly:
public class ServiceFactory
{
private static Dictionary<Type, object> srvs = new Dictionary<Type, object>();
private ServiceFactory()
{
}
public static T GetService<T>(string configName = null)
{
if (!srvs.ContainsKey(typeof(T)))
{
if (String.IsNullOrEmpty(configName))
throw new Exception("configName must be provided by client");
srvs.Add(typeof(T), new ChannelFactory<T>(configName).CreateChannel());
}
return (T)srvs[typeof(T)];
}
}
[DataContract]
public class Customer
{
[DataMember]
public int ID { get; set; }
public Address Address
{
get
{
return ServiceFactory.GetService<IMyService>().GetAddressByCustomerID(ID);
}
}
}
Client-Side:
var srv = ServiceFactory.GetService<IMyService>("MyServiceEndpointConfigName");
// get a Customer DataContract object
var cust = srv.GetCustomerByID(1);
// calls automaticly the GetAddressByCustomerID method
var Console.WriteLine(cust.Address.City);
While I disagree with doing this in the first place, it is interesting to explore the idea.
Taking the overall picture into account: Instances of MyType would be created on the server side and on the client side. They would either be explicitly created by code, or created when the WCF framework deserializes a message. For example, if your Service takes an object of MyType as a parameter, then your client code would have to create an instance and pass it to a WCF call. At this point, the WCF framework will serialize it by invoking all of the getter methods and writing to XML, and then the WCF framework on the server side will create a new copy and call all of the set methods during deserialization.
On the server side, your newly deserialized MyType instance might be able to get the service instance via the following code:
var serviceInstance = (MyService) OperationContext.Current.InstanceContext.GetServiceInstance()
(I don't know if that would work, because the set methods will be called while the MyType instance is being deserialized. Is the current InstanceContext available at this point?)
But on the client side, there isn't any operation context so you cannot call this code.
You could just check if OperationContext.Current is null or not. Or you could hand-code the server side and client side interface definitions, so that the server's implementation of MyType has this extra setter logic while the client's implementation does not. Of course, having two corresponding yet slightly different interface definitions introduces a whole maintenance issue.
Good luck, I'd be interested in how your adventure works out.
精彩评论