如何在.NET中解耦? [英] howto decouple in .NET?

查看:118
本文介绍了如何在.NET中解耦?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这更像是一个C#问题,而不是一个C ++问题,但我最好的机会来解释它是通过与C ++的比较。


好​​的:


在C ++中,您可以转发声明类型。然后可以以类型安全的方式传递对该类型的引用,而不会引入对

类型的依赖。只有需要访问成员的用户才需要类型定义。


C#泛型提供类似的功能,您可以将类型视为

opaque。但是C#和.NET假设类型参数将采用

不同的值,这不是我想要的。这样做的一个结果是

而C ++前向声明可用于所有代码并且自动

在任何地方都指向相同的类型,以在C#中获得相同的效果,类型

论证会像癌症一样传播。此外,由于C#using指令位于
命名空间范围内,因此您无法使用它们来模拟typedef,而是隐式地来回传递类型

参数。我正在寻找的是一个模块范围的

类型参数。


哦......我只是有个主意......让我们我看看C#是否支持通用静态

类。这可能会减轻未定义类型的普遍传播。

实际上,我可能不想声明类本身是静态的,因为

会阻止继承。我的C ++程序员想到使用C#partial class作为一个更强大的命名空间而想到了

,但它可能只是
工作。

This is more of a C# question than a C++ question, but my best chance of
explaining it is via comparison to C++.

Ok:

In C++ you can forward declare a type. Then references to that type can be
passed around in a typesafe way without introducing a dependency on the
type. Only users needing to access the members need the type definition.

C# generics provide a similar capability, where you can treat a type as
opaque. But C# and .NET assume that the type argument will take on
different values, which isn''t what I desire. One effect of this is that
while the C++ forward declaration is available to all code and automatically
refers to the same type everywhere, to get the same effect in C#, the type
arguments would spread like cancer. Also, since C# using directives are at
namespace scope, you can''t use them to emulate a typedef, passing the type
arguments back and forth implicitly. What I''m looking for is a module-wide
set of type arguments.

Oh... I just had an idea... Let me see if C# supports generic static
classes. That might alleviate the pervasive spread of undefined types.
Actually, I might not want to declare the class itself static, because that
prevents inheritance. The C++ programmer in me cringes at the thought of
using a C# partial class as a more powerful namespace, but it might just
work.

推荐答案

这是一个C#问题而不是C ++问题,但我最好的机会是
This is more of a C# question than a C++ question, but my best chance of

解释它是通过与C ++的比较。


好​​的:


在C ++中,你可以转发声明一个类型。然后引用该类型可以以类型安全的方式传递
,而不会引入对

类型的依赖。只有需要访问成员的用户才需要类型定义。


C#泛型提供类似的功能,您可以将类型视为

opaque。但是C#和.NET假设类型参数将采用

不同的值,这不是我想要的。这样做的一个结果就是

而C ++前向声明可用于所有代码而

自动引用相同类型的所有代码,以获得相同的效果
C#中的
,类型参数会像癌症一样传播。另外,由于使用

指令的C#在命名空间范围内,你不能使用它们来模拟

typedef,隐式地来回传递类型参数。我在寻找的是一个模块范围的类型参数集。


哦......我只是有个主意......让我们我看看C#是否支持通用静态

类。这可能会减轻未定义类型的普遍传播。

实际上,我可能不想将类本身声明为静态,因为

会阻止继承。我身上的C ++程序员对使用C#partial class作为更强大的命名空间的想法感到畏缩,但它可能只是起作用。
explaining it is via comparison to C++.

Ok:

In C++ you can forward declare a type. Then references to that type can
be passed around in a typesafe way without introducing a dependency on the
type. Only users needing to access the members need the type definition.

C# generics provide a similar capability, where you can treat a type as
opaque. But C# and .NET assume that the type argument will take on
different values, which isn''t what I desire. One effect of this is that
while the C++ forward declaration is available to all code and
automatically refers to the same type everywhere, to get the same effect
in C#, the type arguments would spread like cancer. Also, since C# using
directives are at namespace scope, you can''t use them to emulate a
typedef, passing the type arguments back and forth implicitly. What I''m
looking for is a module-wide set of type arguments.

Oh... I just had an idea... Let me see if C# supports generic static
classes. That might alleviate the pervasive spread of undefined types.
Actually, I might not want to declare the class itself static, because
that prevents inheritance. The C++ programmer in me cringes at the
thought of using a C# partial class as a more powerful namespace, but it
might just work.



如果我理解你的问题,我认为通常的方式我已经看到

这是通过接口解决的。

我在C#中做过大型项目的几个客户都有指导,

指定一个类总是一个x接口的实现,非常好的b / b
很少没有''自己的方法或属性。


这样他们就可以将接口(有点像COM,如果你想要的话)传递给不同的

个地方。

这消除了对前向声明的需要,附加约束

如果你需要从一个东西转换到另一个东西,你有运行时类型

检查而不是编译时间类型检查


不确定这对你有什么帮助,但也许它很有用。


-

亲切问候,

Bruno van Dooren MVP - VC ++
http://msmvps.com/blogs/vanDoo ren
br **** ******************@hotmail.com


嗨Ben,


是的,我同意在C#newsgroup上发帖会收到更多的C#MVP和

专家的回复/想法。我不确定我是否完全理解你。


为什么不尝试将System.Type作为静态类中的成员?


静态A类

{

Public TypeArg1 As System.Type

}


谢谢。


祝你好运,

Jeffrey Tan

微软在线社区支持

===== =============================================

通过电子邮件收到我的帖子通知?请参阅
http://msdn.microsoft .com / subscripti ... ult.aspx#notif

ications。


注意:MSDN托管新闻组支持服务是针对非紧急问题

如果社区或微软支持人员在1个工作日内做出初步回复是可以接受的。请注意,每个跟随

的响应可能需要大约2个工作日作为支持

专业人士与您合作可能需要进一步调查才能达到

最有效的分辨率。该产品不适用于需要紧急,实时或基于电话的交互或复杂的b $ b项目分析和转储分析问题的情况。这种性质的问题最好通过联系

Microsoft客户支持服务(CSS)处理
href =http://msdn.microsoft.com/subscriptions/support/default.aspx\"target =_ blank> http://msdn.microsoft.com/subscripti...t/default.aspx

======================================== ==========

此帖子按原样提供。没有保证,也没有授予任何权利。

Hi Ben,

Yes, I agree that posting in C# newsgroup will receive more C# MVP and
experts replies/thoughts. I am not sure I understand you completely.

Why don''t you try System.Type as a member in a static class?

Static class A
{
Public TypeArg1 As System.Type
}

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscripti...ult.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscripti...t/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.


如果我理解你的问题,我认为通常的方式我见过
If I understand your question correctly, I think the usual way I have seen

这是通过接口解决的。

我在C#中做过大型项目的几个客户都有指导

指定一个类总是一个x接口的实现与

很少甚至没有自己的方法或属性。


那样他们传递接口(有点像COM,如果你想要的)到不同的

的地方。

这就避免了前方声明的需要,加上约束

,如果你需要施放来自另一件事,你有运行时类型

检查而不是编译时间类型检查
this solved is through interfaces.
Several of my customers who did large projects in C# had guidelines that
specified that a class is always an implementation of x interfaces with
very little to no ''own'' methods or properties.

That way they passed interfaces (A bit COM like if you want) to different
places.
This obviated the need for forward declarations, with the added contraint
that if you needed to cast from one thing to another, you had runtime type
checking instead of compile time type checking



我想我看到你得到了什么在这儿。我不喜欢关于

施放的部分。


我有各种各样的小部件系统。为简单起见,每个小部件都可以生成警报并公开操作。我想分开处理这两个问题的代码

。也就是说,报警记录器应该能够从所有小部件收集报警而无需引用代码

声明您可以对操作执行的操作。用于调整

wazzit计数的按钮应该能够找到并运行正确的操作,而不需要关注警报。恐慌系统基于两者,需要监视关键警报并调用小部件上的重置操作

引起警报。


使用接口,我可以使组件实现IAlarmSite和

IWithOperations。警报类型可以具有类型为

IAlarmSite的Producer属性。 wazzit调整按钮可以使用来自
IWithOperations的方法。但是......恐慌系统存在问题。它可以找出

IAlarmSite引起严重警报的内容,但是没有方法可以运行重置操作,因为它们是IWithOperations的一部分。

运行时强制转换。


在C ++中没有问题。警报类型可能只有组件类的前向

声明,并从

GetProducer()返回指向它的指针。组件类可以公开一个OperationSet *,其中

也是一个不完整的类型。报警记录器包括组件

定义和报警定义,可以获得有关发生的事情的详细信息和

其中。 wazzit调整器可以包含组件定义和

操作集定义,并将所有警报内容保留为不完整类型。

恐慌系统可以包括所有三种。唯一的问题是,如果你的makefile依赖系统没有粗心,你最终可能会违反

ODR违规行为。


..NET,有泛型,有可能解决这个问题,给予

完美的类型安全(C ++模板工作得很好,除了要求

编译一切都在一起)。


泛型< typename组件>

其中组件:IAlarmSite

公共引用类警报

{

...

属性组件^制作人

{

组件^ get(void) {...}

}

};


公共引用类ComponentImpl:IAlarmSite,IWithOperations

{

typedef Alarm< ComponentImplAlarm;

...


BroadcastAlarm(gcnew Alarm());


...

};


等等。


但现在这些通用论点无法控制地传播,就像癌症一样。


公共引用类AlarmCollection

{

列表<报警^ ...; //呃哦,闹钟需要一个类型参数

};


取2:


generic< ; typename组件>

其中组件:IAlarmSite

公共引用类AlarmCollection

{

typedef Alarm< ComponentAlarm;

List< Alarm ^ ...; //更好

};


取3:


generic< typename Component>

其中组件:IAlarmSite

公共引用类AlarmConcern

{

public:

ref class Alarm

{

...

};


ref class AlarmCollection

{

...

};

};


公共引用课程组件:AlarmConcern< Component>,IAlarmSite

{

};


这很漂亮。 前瞻性声明集中和

自动共享。不再需要typedef,这很好

因为它在C#中不可用。配置也是集中的,所以

很容易替换模拟对象。只有一个致命的问题。

继承是将泛型类拉入名称搜索的唯一方法

范围,而.NET只允许单继承。 C ++ / CLI可以绕过这个

,其中:


公共引用类组件:IAlarmSite,IWithOperations

{

typedef AlarmConcern< ComponentAlarmConfiguration;

使用AlarmConfiguration :: Alarm;

使用AlarmConfiguration :: AlarmCollection;

typedef OperationsConcern< ComponentOperationsConfiguration;

// ....

};


这不再那么好了,因为它需要使用每个班级需要申报

。除了C ++ / CLI之外,它在任何语言中都没用。

使用的C#版本不能在课堂内使用,因此它不能指代

一般参数。实际上,我不确定C ++ / CLI是否应该使用

" using"或者typedef,因为名字不是来自基类。


我看到很多请求,并且我自己想要几次,是

有点使用成员指令,就像使用一样,除了它将一个类的静态成员(包括嵌套类型)拉入名称搜索范围。但是

这就是这样一个系统真正闪耀的地方......当用于具有任意嵌套的泛型配置的泛型时。想象一下:


public ref class组件:IAlarmSite,IWithOperations

{

使用成员AlarmConcern< Component> ;; //语法1

使用OperationsConcern< Component> :: *; //语法2

...

};


这完全不需要从中得到静态(密封的

摘要)类。权力是因为通用配置可以通过

传递:


generic< typename Component>

其中Component:IWithOperations

公共引用类RemoteOperationsConcern

{

使用OperationsConcern< Component> :: *;


...

};


你能用现有的

C ++ / CLI建议一种方法来完成类似的事情。 C#语言?

I think I see what you''re getting at here. I don''t much like the part about
casting.

I have a system of widgets of various. Each widgets can, for simplicity''s
sake, generate alarms and expose operations. I want to separate the code
dealing with these two concerns. That is to say, the alarm logger should be
able to collect alarms from all widgets without having to reference the code
declaring what you can do with an operation. The button for adjusting the
wazzit count should be able to find and run the right operation, without
caring about alarms. And the panic system is based on both, needing to
watch for critical alarms and invoke the reset operation on the widget that
caused the alarm.

With interfaces, I could make the component implement IAlarmSite and
IWithOperations. The alarm type could have a Producer property of type
IAlarmSite. The wazzit adjustment button could use methods from
IWithOperations. But... the panic system has a problem. It can find out
what IAlarmSite caused the critical alarm, but there are no methods for
running a reset operation because those are part of IWithOperations.
Runtime cast.

In C++ there would be no problem. The alarm type could have only a forward
declaration of the component class and return a pointer to it from
GetProducer(). The component class could expose an OperationSet* where that
also is an incomplete type. The alarm logger includes the component
definition and the alarm definition and can get details on what happened and
where. The wazzit adjuster can include the component definition and the
operationset definition and leave all the alarm stuff as incomplete types.
And the panic system can include all three. The only issue is that if
you''re careless with your makefile dependency system, you can end up with
ODR violations.

..NET, with generics, has the potential to resolve even that problem, giving
perfect type safety (C++ templates work just as well except for requiring
compiling everything together).

generic<typename Component>
where Component : IAlarmSite
public ref class Alarm
{
...
property Component^ Producer
{
Component^ get( void ) { ... }
}
};

public ref class ComponentImpl : IAlarmSite, IWithOperations
{
typedef Alarm<ComponentImplAlarm;
...

BroadcastAlarm(gcnew Alarm());

...
};

and so forth.

But now those generic arguments spread uncontrollably, like a cancer.

public ref class AlarmCollection
{
List<Alarm^...; // uh-oh, Alarm needs a type argument
};

Take 2:

generic <typename Component>
where Component : IAlarmSite
public ref class AlarmCollection
{
typedef Alarm<ComponentAlarm;
List<Alarm^...; // better
};

Take 3:

generic <typename Component>
where Component : IAlarmSite
public ref class AlarmConcern
{
public:
ref class Alarm
{
...
};

ref class AlarmCollection
{
...
};
};

public ref class Component : AlarmConcern<Component>, IAlarmSite
{
};

This is beautiful. The "forward declarations" are centralized and
automatically shared. The typedef is no longer needed, which is good
because it isn''t available in C#. Configuration is also centralized, so
it''s easy to substitute mock objects. There is just one fatal problem.
Inheritance is the only way to pull a generic class into the name search
scope, and .NET only allows single inheritance. C++/CLI can get around this
partway, with:

public ref class Component : IAlarmSite, IWithOperations
{
typedef AlarmConcern<ComponentAlarmConfiguration;
using AlarmConfiguration::Alarm;
using AlarmConfiguration::AlarmCollection;
typedef OperationsConcern<ComponentOperationsConfiguration ;
// ....
};

This is not so nice anymore, because it requires a using declaration for
every class needed. And it isn''t as useful in any language except C++/CLI.
The C# version of "using" can''t be used inside a class, so it can''t refer to
a generic parameter. Actually, I''m not sure if the C++/CLI should use
"using" or typedef, because the names aren''t coming from a base class.

What I''ve seen a lot of requests for, and wanted a few times myself, is a
sort of "using members" directive, like using, except it pulls static
members (including nested types) of a class into the name search scope. But
this is where such a system would really shine... when used for
configuration of generics, with arbitrary nesting. Imagine:

public ref class Component : IAlarmSite, IWithOperations
{
using members AlarmConcern<Component>; // syntax 1
using OperationsConcern<Component>::*; // syntax 2

...
};

This totally obviates the perceived need to derive from a static (sealed
abstract) class. The power is because the generic configuration can be
passed though:

generic <typename Component>
where Component : IWithOperations
public ref class RemoteOperationsConcern
{
using OperationsConcern<Component>::*;

...
};

Can you suggest a means to accomplish something similar, with the existing
C++/CLI and C# languages?


这篇关于如何在.NET中解耦?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆