WCF DataContract class with methods

2019-07-01 11:36发布

问题:

This is more of a philosophical/best-practice sort of question rather than a technical problem.

Are there any strong arguments against writing a DataContract class with methods that are to be used server-side only? Or what about additional properties that are not decorated with the DataMember attribute?

For example:

[DataContract]
public class LogEntry
{
  [DataMember]
  public string Message { get; set; }
  [DataMember]
  public string Severity { get; set; }

  public string SomeOtherProperty { get; set; }

  ...

  public void WriteToDatabase()
  {
    ...
  }
}

Not doing it seems like an awful lot of extra work that I would prefer to avoid, although using extension methods could make it easier. But, as a good developer, I am wondering if it is bad practice to do so.

回答1:

Technically you can add implementation in the same class with the data contract. Only those properties attributed will get serialized.

In your example, you had the object, transport and how to write to database in the same class:

[DataContract]
public class LogEntry
{
    ...

     public void WriteToDatabase()

I would recommend that your front end code and objects that get serialized is separate from your persistance. I would even recommend a separate database access layer which has no knowledge of the layers or responsibility of the layers above it which own transport and business logic.

If the database persistence is in your data contract and transport layer, over time, it will be impossible to tease apart and replace layers if you need to - it will be one blob of code.

Separating the layers also helps with testing. Being able to test a unit of code without all the dependencies of a full system is valuable. For example, if you separate your database persistance and even decouple it with an interface, for unit testing your business logic, you could replace the persistance with a subset in-memory implementation.

One issue becomes how you pass those objects down to the DAL if it has no knowledge of the objects that get transported. To enforce separation, I've seen a types dll which simply contains these structures with data contract decorations, a services layer that owns the transport and a BLL/DAL which both reference the types dll.

Hope that helps.



回答2:

You certainly can add anything you want to the type because as far as WCF is concerned, only memebers that have explicitly opted-in as DataMembers are part of the contract and will be serialized as such.

I think that it is cleaner to not put extraneous members into a contract as that can be confusing when you are using the type.



回答3:

Actually, it really depends on the context

by context I mean: First project management context : money budget/time/developpers level/expected life time of your project Then WCF context : is it a webservice (wsdl) or a namedpipe transfer

If you are short on everything and you do not expect anybody than the clients you are developping to connect to the web service and you feel confortable with this approach do it.

In all the other case, I would suggest to cleanly split the contract code from implementation details.

Note that in a WCF namedpipe context, you could be interested in implementing only once this contract in an assembly shared by both the clients and the server. In this case you risk to expose to clients signatures of the server.