SCSF - Part 7 Introduction to Services in the CAB

来源:互联网 发布:儿童画画的软件 编辑:程序博客网 时间:2024/05/20 10:13

Introduction

Part 6 of this series of articles concluded our discussion of dependency injection in the CAB.

part6 总结了我们关于dependency injection  在CAB里的讨论

 

This article and part 8 of the series will discuss services in the CAB in some more detail. This article discusses services in general terms, whilst part 8 will show in detail the various ways of creating and using services.

这篇文章会更深入地讨论 CAB 里的services 的一些细节, 这篇文章会谈论关于services 的一个大概, 而part8会讨论一些创建和使用services的不同方法。

 

What is a ‘Service’?

You probably already have an intuitive idea of what a ‘service’ is in computer programming. Wikipedia defines a service in the context of a Service-oriented architecture as ‘a discretely defined set of contiguous and autonomous business or technical functionality’. The CAB documentation defines a service as ‘a supporting class that provides functionality to other components in a loosely coupled way’. CabPedia has a good definition:

‘Services allow easy access to a chunk of functionality that may be used frequently throughout an application. Error handlers, loggers and the event broker are good examples of functionality that can be exposed as a service.’

So think of a service as a chunk of related functionality. In the CAB each service is exposed through one class (and maybe an associated interface) that provides a gateway into the functionality.

我想你肯定早就对 ‘service’ 这个词 在计算机编程上 领域的左右有个直觉上的认识,Wikipedia  这个人定义service  为 。。。。这里没完全看明白     ╮(╯▽╰)╭。       CAB 的文档 定义service  为一种为其他组件提供功能的松耦合的的支持类。 CabPedia 有一个更好的定义

‘Services 为在整个application里一些经常使用的功能提供一个很容易的通道。Error handlers, loggers and the event broker都是可以用来说明什么是service的很好的例子。  所以,把service 看做是一种功能块。在CAB 里,每一种service 被暴露在一个类(或者一个相关的接口)从而成为我们提供功能的一个大门。

 

We have already seen how to use CAB services in earlier articles in this series. Part 2 described how one of the collection classes on a WorkItem is the Services collection. Part 5 showed how we can inject a service (which is just any item in the Services collection) by using a setter with a ServiceDependency attribute. We saw that we can inject the WorkItem itself in this way. This is because a WorkItem is automatically a ‘service’ in its own Services collection.

我们早就在之前的文章里看到如何使用CAB services ,part2描述了怎样的 的 collection class 在workitem是一个Services collection,part5展示了我们如何使用ServiceDependency 注入一个service,我们看到我们可以通过这种方法注入WorkItem本身,这是因为WorkItem  是一种自动的服务在他的Services collection里。

 

 

The Services Collection versus the Items Collection

Part 5 of this series of articles also touched on the fact that the Services collection on a WorkItem has some important differences with the Items collection. This is separate from the fact that the intent of the two collections is different: services are meant to be objects that expose chunks of related functionality, whereas items are just any objects that we want to be able to access through the WorkItem.

The differences between the collections can be confusing so I’ll start this discussion by comparing the two collections.

part5 也提及到了  Services collection  和 Items collection 有些重要的不同, 这是因为这两者的目的是不同的,services 是用来提供功能的,而items 是任何我们想要能够触及到的objects。

这两者之间的区分可能会有些让人感到困惑, 我会通过比较这两者来展开我们的讨论。

 

 

Services vs Items (1): Unique Types

The most obvious of these conceptual differences is the fact that the Services collection can only ever contain one object of a given type. If we attempt to add a second service of the same type to a Services collection we get an ArgumentException with message ‘A service of this type already exists’.

最明显的的不同是Services collection  只能含有一种类型的一个对象。如果我们尝试加入第二个,我们会得到一个错:‘A service of this type already exists’.

In contrast, the Items collection of a WorkItem can contain multiple objects of the same type. To accommodate this all objects added to the Items collection are assigned a unique string ID, either by the user explicitly, or by the CAB implicitly (a random GUID is assigned).

相反, 在WorkItem 的 Items collection 里, 可以含有同一种类型的不同object,每一个object都被加上了唯一的ID,无论是用户自己显式地加入,还是cab自己会随机的产生一个GUID

 

However, this means that if we want to access a specific object in the Items collection we have to know its ID. Hence the ComponentDependency attribute, which injects an object from the Items collection, needs an ID passed as an argument.

然而,这意味着如果我们想取得item collection里特定的object,我们不得不得知道它的id,因此ComponentDependency 属性需要一个ID传入到他的attribute里。

We don’t need an ID to access an object in the Services collection. Because we can identify a service uniquely by its type the ServiceDependency attribute can be used to inject a service without the need for any ID.

对于Services 我们不需要ID,我们可以通过唯一的service  type 来注入一个service

 

Services vs Items (2): Searching the Hierarchy

Another difference between the Services collection and the Items collection is what happens if we request a specific object from the collection and the CAB can’t find it in the WorkItem’s collection. When trying to retrieve a service the CAB will then search in any parent WorkItem’s Services collections for the object, and return it if found. With the Items collection the CAB will just return null if the object cannot be found in the specific Items collection for the WorkItem.

 另一个不同就是我们在请求这两者的时候的所发生的不同,如果我们在某个workitem里请求一个service,而CAB无法找到它,cab会寻找它的parent workitem’s的service collections,然后告诉你有没有找到,如果是Items collection  CAB 只会在当前的workitem里找。

 

 

Basic Service Example without Dependency Injection

simple example of how to create and use a service without using dependency injection is available. The ‘service’ here is just one class (MyService) with one method (GetHello) that returns the string “Hello World”:

一个简单的例子告诉我们如何不用依赖注入创建和使用service ,这里的service是一个很简单的class返回“Hello World”:

public class MyService{    public string GetHello()    {        return "Hello World";    }}
We can make this simple class into a CAB service by adding it to the Services collection of a WorkItem. In this case we add it to the Services of the RootWorkItem in AfterShellCreated:

我们可以把这个class加到 Services collection 里。在AfterShellCreated 这个函数里加。

protected override void AfterShellCreated()          
{              
     RootWorkItem.Services.AddNew<MyService>();              
     UseMyService();              
    ...

We use the service in routine UseMyService. Here we retrieve the service using the Get method of the Services collection, telling it the type of the service we want to retrieve. We then call our method and output the results to the Output window:

UseMyService函数里调用它,我们只需告诉它我们要用哪个service

private void UseMyService(){    MyService service = RootWorkItem.Services.Get<MyService>();    System.Diagnostics.Debug.WriteLine(service.GetHello());}

It’s as simple as that. The full code also outputs all of the services that have been set up in the application, and shows that our MyService service is in there. You can see that there are a surprisingly large number of services set up by default by the CAB even in a simple application of this kind:

 就是那么简单,。。。。。。。 你可以看到有好多默认的服务

SEVICES:
[Microsoft.Practices.CompositeUI.WorkItem, Microsoft.Practices.CompositeUI.WorkItem]
[Microsoft.Practices.CompositeUI.Services.ICryptographyService, Microsoft.Practices.CompositeUI.Collections.ServiceCollection+DemandAddPlaceholder]
[Microsoft.Practices.CompositeUI.ITraceSourceCatalogService, Microsoft.Practices.CompositeUI.TraceSourceCatalogService]
[Microsoft.Practices.CompositeUI.Services.IWorkItemExtensionService, Microsoft.Practices.CompositeUI.Services.WorkItemExtensionService]
[Microsoft.Practices.CompositeUI.Services.IWorkItemTypeCatalogService, Microsoft.Practices.CompositeUI.Services.WorkItemTypeCatalogService]
[Microsoft.Practices.CompositeUI.IWorkItemActivationService, Microsoft.Practices.CompositeUI.SimpleWorkItemActivationService]
[Microsoft.Practices.CompositeUI.Services.IAuthenticationService, Microsoft.Practices.CompositeUI.Services.WindowsPrincipalAuthenticationService]
[Microsoft.Practices.CompositeUI.Services.IModuleLoaderService, Microsoft.Practices.CompositeUI.Services.ModuleLoaderService]
[Microsoft.Practices.CompositeUI.Services.IModuleEnumerator, Microsoft.Practices.CompositeUI.Services.FileCatalogModuleEnumerator]
[Microsoft.Practices.CompositeUI.Commands.ICommandAdapterMapService, Microsoft.Practices.CompositeUI.Commands.CommandAdapterMapService]
[Microsoft.Practices.CompositeUI.UIElements.IUIElementAdapterFactoryCatalog, Microsoft.Practices.CompositeUI.UIElements.UIElementAdapterFactoryCatalog]
[Microsoft.Practices.CompositeUI.WinForms.IControlActivationService, Microsoft.Practices.CompositeUI.WinForms.ControlActivationService]
[Shell.MyService, Shell.MyService]

Splitting the Interface from the Implementation

As we all know, for services it is considered good practice to separate our interface from our implementation. This allows us to vary the way the service is implemented without having necessarily to change the interface and thus affect client code. This can be important in a composite smart client application where different teams may be working on different parts of the application.

正如我们所知的, services 可以看做是一种实践来分隔interface 和implementation,这允许我们实现service的同时可以不改变接口和用户代码。这在cab里很重要因为不同的team也许在开发不同的部分

 

 

This can be very easily done for our basic example. We simply set up an interface with our method signature in it:

    public interface IMyService      {          string GetHello();      }

We then implement this interface on our MyService class:

    public class MyService : IMyService      {          public string GetHello()          {              return "Hello World";          }      }

Another change we need to make is how we create the service. We want the type associated with it in the Services collection to be IMyService, but clearly we need to tell the CAB that it is creating an object of type MyService (it can’t just instantiate the interface). The syntax for this is as below:

            RootWorkItem.Services.AddNew<MyService, IMyService>();

The UseMyService method now retrieves the service using the IMyService interface. It doesn’t need to know about the MyService class:

这里就不需要知道MyService class了

private void UseMyService(){    IMyService service = RootWorkItem.Services.Get<IMyService>();    System.Diagnostics.Debug.WriteLine(service.GetHello());}

These are the only changes that need to be made. The code for this example is available.

Conclusion

That concludes our initial introduction to services in the CAB. Part 8 will show the various options for creating and using services in more detail.

 

References

CabPedia page on Services
http://www.cabpedia.com/index.php?title=Services

Wikipedia on Services in an SOA
http://en.wikipedia.org/wiki/Service_%28Systems_Architecture%29

原创粉丝点击