1

我有一个 C# 客户端和一个 java 服务器。我有来回传输的数据对象。让我们称它们为 FooData.cs,其中一切都只是一个 get 和一个 set(没有逻辑)

FooData data = new FooData();
data.Price = 10;
data.Quantity = 20;

我有其他派生字段,我想在应用程序中使用,但不需要通过网络发送,所以我有另一个类

FooWrapper.cs。

我将数据对象注入到包装器中

FooWrapper wrapper = new FooWrapper(Foodata);
wrapper.Price = 10;
wrapper.Quantity = 20;
double total  = wrapper.GetTotal();

并且包装器具有许多与数据对象相同的属性(我们只是向下委托),或者包装器也具有许多计算属性。包装器的唯一状态是数据对象(没有其他成员变量)

我们就使用此模型与使用转换器进行了辩论。转换器的方式是使用 FooBusinessObject 代替 FooWrapper,而不是注入“在线”对象,我们调用一个转换方法,将所有数据从在线对象传递到业务对象。

FooData data = new FooData();
FooBusinessObject busObj = new FooBusinessObject();
busObj.Price = data.Price;
busObj.Quant= data.Quantity;
double total  = busObj.GetTotal();

关于更好的任何想法(包装器与业务对象/转换器)

4

4 回答 4

1

编写问题的方式,我能看到的唯一真正区别是您是通过构造函数传递 fooData 实例还是调用构造它的单独方法,但在第一个方法中隐含的是 Wrapper 对象保留对原始对象,而在第二种方法中,在我看来,您似乎避免了这种联系。

I think the underlying issue is really if you want to keep a reference to the original object. This may sometimes be relevant if the original object contains state that you will not be exposing to your application but could be necessary to perform updates.

If this is not the case then I would try to hide the wire-level objects away from your business logic. Part of the intention of wrapping is to protect your code from the details of the wire-level stuff, and the further up in the stack you let these things seep, the greater the chance they'll be used where not intended, increasing unintentional coupling.

于 2009-02-08T13:04:23.517 回答
1

(edit) What version of C# are you using? With C# 3.0 you could place the "logic" bits (calculations etc) in extension methods in a busines logic assembly, but still see them via the DTO - i.e.

(data layer)

public class Foo {
    public int Bar {get;set;}
}

(business layer)

static class FooExt {
    public static int Blop(this Foo foo) {return 2 * foo.bar;}
}

(ui layer)

Foo foo = ...
int blop = foo.Blop();

What model are you using to transfer the data? web services? xml? data-contracts? binary? Most would allow you to ignore the extra properties without any extra code (i.e. no need for a wrapper/facade object):

XmlSerializer:

[Serializable]
public class MyData {
    public int Foo {get;set;} // is sent
    [XmlIgnore]
    public int Bar {get {...} set {...}} // is ignored
}

DataContractSerializer:

[DataContract]
class MyData {
    [DataMember]
    public int Foo {get;set;} // is sent
    public int Bar {get {...} set {...}} // is ignored
}

If you are talking binary, there are portable java/C#-friendly models such as "protocol buffers" - Jon Skeet has a C# port of the official java version (allowing you to use very similar code on both sides) - or I have a more C#-idiomatic version (protobuf-net):

ProtoSerializer:

[ProtoContract]
class MyData {
    [ProtoMember(1)]
    public int Foo {get;set;} // is sent
    public int Bar {get {...} set {...}} // is ignored
}
于 2009-02-08T13:26:00.493 回答
0

Rather than thinking in terms of objects that go back and forth, could you think instead of the business events that one side needs to notify the other and the minimum amount of data required to describe each one?

于 2009-02-08T15:00:28.587 回答
0

I'd tend to use the wire object to build the other one, and not wrap it. "How the data is transferred" and "how the object is stored in memory" are two different concerns, and not mixing them is a generally good idea. At some point, you may use a different 'wire' technology not compatible with your existing wire objects, and if that happens, I'd rather modify a converter class than my core business logic.

This also gives you the flexibility to modify your wire objects to contain more/less/different data without having to impact your core business functionality. An all-around win, in my book.

于 2009-08-06T05:27:26.663 回答