ICE框架之Sclice2CSharp映射---类的映射

   Slice 类映射到同名的C# 类。对于每一个Slice 数据成员,生成的类都有一个对应的public 数据成员(就像结构和异常的情况),而每一个操作都有一个对应的成员函数。考虑下面的类定义:

class TimeOfDay {

    short hour;          // 0 - 23

    short minute;        // 0 - 59

    short second;        // 0 -59

    string format();     // Return time as hh:mm:ss

};

Slice 编译器为这个定义生成这样的代码:

public interface TimeOfDayOperations_

             {

                  string format(Ice.Current __current);

             }

             public interface TimeOfDayOperationsNC_

             {

                  string format();

             }

             public abstract class TimeOfDay

                  : Ice.ObjectImpl,

                     TimeOfDayOperations_,

                     TimeOfDayOperationsNC_

             {

              public short hour;

                      public short minute;

              public short second;

              public TimeOfDay()

              {

              }

              public TimeOfDay(short hour, short minute, short second)

              {

                   this.hour = hour;

                   this.minute = minute;

                   this.second = second;

              }

              public string format()

              {

                   return format(new Ice.Current());

              }

              public abstract string format(Ice.Current __current);

             }

关于生成的代码,注意以下几点:

1.           编译器生成了叫作 TimeOfDayOperationsTimeOfDayOprationsNC_的操作接口。对于类中的每一个 Slice 操作,在操作接口中都有一个对应的方法。

2.           生成的类继承自Ice.Objet,这意味着所有的类默认继承自Ice.Object,Ice.Object是所有类的祖先,注意Ice.Object不同于Ice.ObjectPrx,也就是说,你不能在应该传递代理的地方使用class实例,反之亦然。
如果一个类只有数据成员,没有操作,则Slice2C#编译器生成一个非虚类(non_abstract class).

3.           编译器生成的类为每个slice数据成员生成了一个公共数据字段。

4.           编译器生成的类从操作接口中继承了所有成员函数

5.           编译器生成的类拥有两个构造函数

上面只是简短的说了一下,下面让我们来详细的说明一下每个部分。

操作接口 

<interface-name>Operations_功能接口中的方法都有一个附加的Ice.Curreet类型的参数,而在<interface-name>OprationsNC_功能接口中的方法则都没有这个参数。对于没有显式指定Ice.Current类型参数的方法,它其实有一个默认的Ice.Current参数。

如果一个类只有数据成员,而没有方法,那么编译器将不会生成上面所说的两个操作接口。

继承自Ice.Object

像接口一样,所有的类都隐式的继承自一个公共基类Ice.Object.,类继承自Ice.Object而不是Ice.ObjectPrx(接口继承自Ice.ObjectPrx)。所以,你不能在期望得到代码的地方指定一个类,反之亦然,这是因为他们的基类型是不兼容的。

Ice.Object的定义如下:

namespace Ice

              {

                   public interface Object : System.ICloneable

                   {

                        int ice_hash();

                        bool ice_isA(string s);

                        bool ice_isA(string s, Current current);

                       void ice_ping();

                       void ice_ping(Current current);

                       string[] ice_ids();

                       string[] ice_ids(Current current);

                       string ice_id();

                       string ice_id(Current current);

                       void ice_preMarshal();

                       void ice_postUnmarshal();

                  }

             }

* ice_hash

这个方法返回类的哈希键。

* ice_isA

这个方法当对象支持给定的类型ID时返回true,否则返回false.

* ice_ids

这个方法返回类在运行时的真正类型ID,

* ice_preMarshal

Ice run time在整编一个对象的状态前会调用这个方法,这就给子类提供了一个验证数据成员的机会。

* ice_postUMarshal

Ice run time在解编一个对象的状态后,会调用这个方法。如果子类希望执行附加的初始操作的话,可以重写这个方法。

注意,生成的类并没有重写GetHaseCode和Equals方法,这意味着类之间的比较是比较引用,而不是比较值。另外类还有提供了浅copy功能的Clone方法。

类的数据成员

默认情况下,类数据成员的映射就像结构和映射一样,对每一个数据成员,生成的类中都有一个对应的公共数据字段。

如果你想限制数据成员的访问,你可以用protected元指令改变数据成员的可见。Protected元指令告诉编译器,生成的类中数据成员的可见性为protectd,这意味着数据成员只能在类内部和类的子类间访问,而不能其它地方访问。例如,如下的slice定义:

class TimeOfDay {

                   ["protected"] short hour;           // 0 - 23

                   ["protected"] short minute; // 0 - 59

                   ["protected"] short second; // 0 - 59

                  string format();          // Return time as hh:mm:ss

             };

上面的silce定义生成的代码如下:

public abstract class TimeOfDay

                   : Ice.ObjectImpl,

                     TimeOfDayOperations_,

                     TimeOfDayOperationsNC_

             {

                  protected short hour;

                  protected short minute;

                  protected short second;

                  public TimeOfDay()

                 {

                 }

                 public TimeOfDay(short hour, short minute, short second)

                 {

                      this.hour = hour;

                     this.minute = minute;

                      this.second = second;

                 }

                 // ...

             }

如果一个类的所有数据成员都是protected的话,你可以将protected元指令应用在类上,而不用再分别指定每个成员。例如,我们可以重写上面的slice定义。

["protected"] class TimeOfDay {

                 short hour;              // 0 - 23

                 short minute;            // 0 - 59

                 short second;            // 0 - 59

                 string format();         // Return time as hh:mm:ss

            };

另外,如果将clr:property元指令和protected元指令结合使用,那么在生成的类中,将会出现protected可见性的属性,

类的操作

类的操作被映射到虚方法,这意味着,如果一个类有成员函数(就像上面的TimeOfDay类),你必须提供一个实现成员函数的类,而这个类继承自生成的类:

public class TimeOfDayI : TimeOfDay

             {

                  public string format(Ice.Current current)

                  {

                       return     hour.ToString("D2") + ":"

                                + minute.ToString("D2") + ":"

                                + second.ToString("D2");

                  }

             }

类工厂

创建了这样的类之后,我们有了一个实现,可以实例化 TimeOfDayI类,但我们不能把它作为返回值进行接收,也不能用作某个操作调用的输出参数。要想知道为什么,考虑下面的简单接口:

   interface Time {

              TimeOfDay get();

          };

当客户调用get操作时,Ice run time 必须实例化TimeOfDay类,返回它的一个实例。但TimeOfDay是一个抽象类,不能实例化。除非我们告诉它,否则 Ice run time 不可能魔法般地知道我们创建了一个TimeOfDayI类,实现了 TimeOfDay抽象类的 format抽象操作。换句话说,我们必须给Ice run time 提供一个工厂,这个工厂知道 TimeOfDay抽象类有一个 TimeOfDayI具体实现。Ice::Communicator接口为我们提供了所需的操作:

          module Ice {

              local interface ObjectFactory {

                  Object create(string type);

                  void destroy();

              };

              local interface Communicator {

                  void addObjectFactory(ObjectFactory factory, string id);

                  void removeObjectFactory(string id);

                  ObjectFactory findObjectFactory(string id);

                  // ...

              };

          };

要把我们的 TimeOfDayI类的工厂提供给 Ice run time ,我们必须实现  ObjectFactory接口:

          class ObjectFactory

                  extends Ice.LocalObjectImpl

                  implements Ice.ObjectFactory {

              public Ice.Object create(String type) {

                  if(type.equals("::TimeOfDay")) {

                      return new TimeOfDayI();

                   }

                  assert(false);

                  return null;

              }

              public void destroy() {

                  // Nothing to do

              }

          }

Ice run time 会在需要实例化TimeOfDay 类时调用对象工厂的create操作;并且会在工厂解除注册、或其Communicator销毁时调用工厂的 destroy操作。

create方法的参数是要实例化的类的类型ID。对于我们的TimeOfDay 类,其类型 ID "::TimeOfDay"。我们的create 实现会检查类型 ID:如果是"::TimeOfDay",就实例化并返回一个TimeOfDayI对象。如果是其他类型 ID,断言就会失败,因为它不知道怎样实例化其他类型的对象。

假定我们有一个工厂实现,比如我们的 ObjectFactory,我们必须把这个工厂的存在告知Ice run time

          Ice.Communicator ic = ...;

          ic.addObjectFactory(new ObjectFactory(), "::TimeOfDay");

现在,每当 Ice run time 需要实例化类型ID "::TimeOfDay"的类时,它就会调用已注册的ObjectFactory 实例的create方法。

当你调用Communicator::removeObjectFactory 时,或者Communicator销毁时, Ice run time 就会调用对象工厂的destroy操作。这样,你就有了清理你的工厂使用的任何资源的机会。当工厂仍然注册在Communicator 上时,不要调用工厂的destroy——如果你这样做了,Ice run time 不知道这件事情的发生,取决于你的destroy 实现所做的事情,当Ice run time 下一次使用工厂时,这可能会导致不确定的行为。

注意,你不能针对同一个类型ID 两次注册工厂:如果你这样做了,Ice  run time 就会抛出AlreadyRegisteredException。与此类似,如果你试图移  除一个并没有注册过的工厂,Ice run time 就会抛出 NotRegisteredException

最后,要记住,如果一个类只有数据成员,没有操作,你无需为了传送这样的类的实例而创建并注册对象工厂。只有当类有操作时,你才需要定义并注册对象工厂。

LocalObject继承

注意,前面的例子中的工厂实现扩展了 Ice.LocalObjectImpl。对象工厂是一个本地对象,从Ice.LocalObject继承了一些操作,比如 ice_hash Ice.LocalObjectImpl类提供了这些操作的实现,所以你无需自己实现它们。

般而言,所有的本地接口都是从 Ice.LocalObject继承的,而所有的本地接口(比如对象工厂或 servant 定位器的实现,都必须从 Ice.LocalObjectImpl继承。

类的构造函数

生成的类有两个构造函数,一个是无参的默认构造函数,另一个是将全部数据成员作为参数的构造函数,后一个构造函数允许你在声明对象时就初始化数据成员的值,比如:

TimeOfDayI tod = new TimeOfDayI(41,45, 00);

对于子类来说,有参的构造函数包括全部的数据成员,包括从基类继承来的数据成员。比如,考虑下面的Slice定义:

class TimeOfDay {

                  short hour;              // 0 - 23

                  short minute;            // 0 - 59

                  short second;            // 0 - 59

             };

             class DateTime extends TimeOfDay {

                  short day;               // 1 - 31

                  short month;             // 1 - 12

                  short year;              // 1753 onwards

             };

上面的定义生成的代码如下:

public class TimeOfDay : Ice.ObjectImpl

             {

                 public TimeOfDay() {}

                 public TimeOfDay(short hour, short minute, short second)

                  {

                       this.hour = hour;

                       this.minute = minute;

                       this.second = second;

                  }

                  // ...

             }

            public class DateTime : TimeOfDay

             {

                 public DateTime() : base() {}

                 public DateTime(short hour,

                                      short minute,

                                      short second,

                                      short day,

                                      short month,

                                      short year) : base(hour, minute, second)

                  {

                      this.day = day;

                      this.month = month;

                      this.year = year;

                  }

                  // ...

             }

也就是说,如果你想实例化并初始化一个DataTime类,那么你要么使用无参的默认构造函数,要么你就调用有参的构造函数,当然,这时你就得指定所有数据成员的值,包括那些从DataTime的基类继承来的数据成员。

原文地址:https://www.cnblogs.com/zhangronghua/p/1203958.html