我怎么能传递一个命名空间的方法? [英] How can I pass a namespace to a method?

查看:96
本文介绍了我怎么能传递一个命名空间的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 命名空间MyOldService 
{
公共MyNewService.AddressList ToPrivateAddressList()
{
MyNewService.AddressList privAddrList =新MyNewService.AddressList() ;

privAddrList.creator =(MyNewService.AddressListCreator)this.creator;
privAddrList.listId = this.listId;
privAddrList.listIdSpecified = this.listIdSpecified;
privAddrList.listName = this.listName;
privAddrList.listType =(MyNewService.AddressingMode)this.listType;
privAddrList.lastModified = this.lastModified;
privAddrList.lastModifiedSpecified = this.lastModifiedFieldSpecified;

如果(this.siteList = NULL&放大器;!&安培; this.listType == MyOldService.AddressingMode.XDAddressingModeSiteIDList)
{
privAddrList.siteList =新长[this.siteList 。长度];
Array.Copy(this.siteList,privAddrList.siteList,this.siteList.Length);
}
...



原来写入复制定义的列表SOAP命名空间MyOldService一类相同的布局中一个新的命名空间MyNewService。问题是,用香皂类的,如果我导入MyOldService命名空间到第三个命名空间,说MyOtherAppService,那么我的AddressList中类成为了第三个命名空间中的一员,因此被引用。



所以,而不是重复的代码,我想用仿制药(我理解是行不通的,因为我改变了命名空间,而不仅仅是一个固定的类似的东西装饰它(或以某种方式调整)输入[有多种类型,我从每个命名空间需要,这可以从片段中可以看出])为使这一地址列表转换为任何需要的命名空间对应的类。 ?可能的



修改:在回应一些下面的意见,我会尽力来定义我想要一个更好的例子做的。



这是通过Web引用的WSDL进口三大类(不,这不会编译,只是为了说明的实例)。该班AddressList中都具有相同的布局

 命名空间
{
枚举模式{};
枚举造物主{};

类ATypeClass {}

公共部分类AddressList中
{
INT ID;
枚举模式模式;
枚举造物主的创造者
长[]站点列表;
ATypeClass [] cspList;
}
}

命名空间B
{
枚举模式{};
枚举造物主{};

类BTypeClass {}

公共部分类AddressList中
{
INT ID;
枚举模式模式;
枚举造物主的创造者
长[]站点列表;
BTypeClass [] cspList;
}
}

命名空间C
{
枚举模式{};
枚举造物主{};

类CTypeClass {}

公共部分类AddressList中
{
INT ID;
字符串名称;
枚举模式模式;
枚举造物主的创造者
长[]站点列表;
CTypeClass [] cspList;
}
}



我将扩展在命名空间的局部类一种新的方法:

 命名空间
{
公共部分类AddressList中
{
公共T.AddressList ToPrivateAddressList< T>()
{
T.AddressList privAddrList =新T.AddressList();

privAddrList.creator =(T.Creator)this.creator;
privAddrList.id = this.id;
privAddrList.name = this.name;
privAddrList.mode =(T.MODE)this.mode;

如果(this.siteList = NULL&放大器;!&安培; this.listType == Mode.XDAddressingModeSiteIDList)
{
privAddrList.siteList =新长[this.siteList.Length ];
Array.Copy(this.siteList,privAddrList.siteList,this.siteList.Length);
}

}
}
}

注意问题的一部分,除了类不同的命名空间的每一部分,是也可从不同的命名空间的枚举



最后,我想象调用它像这样(虽然我知道我不能真正做到这一点,我正在寻找一个解决方案,是大致一样优雅):

  B.AddressList AL1 = A.AddressList.ToPrivateAddressList< B>(); 
C.AddressList AL1 = A.AddressList.ToPrivateAddressList&所述c取代;();


解决方案

我想你要找的是一个接口, 。在其中,关键字在泛型类型定义



从你的代码,我看到你有这样的:




  • 可以转换A型b型

  • <方法LI>是由具有相同名称的分配属性做到这一点
  • ,然后返回新的b型

  • 的类型可以驻留在不同的命名空间(但目前具有相同的名称)

  • 部分



而不是依赖于同名(你可以使用反射可以达到你想要的效果),你应该让每个类实现一个包含公共属性的一个接口。这样,你保留编译时类型安全:

 公共接口ICommonAddress 
{
INT ID {得到;组; }
模式模式{搞定;组; }
造物主的创造者{搞定;组; }
长[] {站点列表获得;组; }
ICommonAddress CreateAddress();
}

现在你可以重构你这样的类(当然,你得改变你的领域进入的属性,但我假设你有他们作为已经属性:

  //如果你原来的局部类生成自动,它是确定放置
//这个定义在另一个文件中,系统会继续工作,只要
//命名空间,类名和编译单元(必须是同一个项目)都是一样的
公共部分类AddressList中:ICommonAddress
{
INT ID {获取;集;}
模式模式{获取;集;}
造物主的创造者{得到;设置;}
长[]站点列表{获得;设置;}
ATypeClass [] cspList;

ICommonAddress CreateAddress()
{
返回新AddressList中(); //注意!你甚至可以有你的ctor私人
}
}

如果你这样做,你让每个AddressList中的类型,你可以改变你的通用方法如下,它会自动工作,包括向您展示的共同可用属性的智能感知。此外,实现它作为一个扩展方法,所以它适用于所有AddressList中的类型(这是你的情况比使用部分越好):

 公共牛逼ToPrivateAddressList< T>(这ICommonAddress _this)
,其中T:ICommonAddress
{$ b $(b T)privAddrList = _this。 CreateAddress();

//这个现在正常工作,而无需进行转换
privAddrList.creator = _this.creator;
privAddrList.id = _this.id;
privAddrList.name = _this.name;
privAddrList.mode = _this.mode;
}

现在,如果您导入到这个扩展方法的引用,可以调用 ToPrivateAddressList()您拥有任何类型:

  A.AddressList a_address = A.AddressList.CreateAddress(); //或新A.AddressList()
B.AddressList AL1 = a_address.ToPrivateAddressList< B.AddressList>();
C.AddressList AL1 = a_address.AddressList.ToPrivateAddressList< C.AddressList>();


namespace MyOldService
{    
    public MyNewService.AddressList ToPrivateAddressList()
    {
        MyNewService.AddressList privAddrList = new MyNewService.AddressList();

        privAddrList.creator = (MyNewService.AddressListCreator)this.creator;
        privAddrList.listId = this.listId;
        privAddrList.listIdSpecified = this.listIdSpecified;
        privAddrList.listName = this.listName;
        privAddrList.listType = (MyNewService.AddressingMode)this.listType;
        privAddrList.lastModified = this.lastModified;
        privAddrList.lastModifiedSpecified = this.lastModifiedFieldSpecified;

        if (this.siteList != null && this.listType == MyOldService.AddressingMode.XDAddressingModeSiteIDList)
        {
            privAddrList.siteList = new long[this.siteList.Length];
            Array.Copy(this.siteList, privAddrList.siteList, this.siteList.Length);
        }
        ...

Originally written to copy a list defined in a SOAP namespace MyOldService to a class of the same layout in a new namespace MyNewService. The problem is, with soap classes, if I import the MyOldService namespace into a third namespace, say MyOtherAppService, then my AddressList class becomes a member of that third namespace and is referenced as such.

So, rather than duplicating the code, I'd like to decorate it (or adjust it somehow) with something akin to generics (which I understand won't work because I'm altering the namespace, not just one fixed type [there are multiple types I need from each namespace, as can be seen from the snippet]) to allow this to convert the address list to the corresponding class in whichever namespace is needed. Possible?

Edit: In response to some of the comments below, I'll try to define a better example of what I'm trying to do.

Three classes imported from WSDLs via web references (no, these won't compile, just examples for illustration). The classes AddressList all have the same layout.

namespace A
{    
    enum Mode {};
    enum Creator {};

    class ATypeClass {}

    public partial class AddressList
    {
        int id;
        enum Mode mode;
        enum Creator creator
        long[] siteList;
        ATypeClass[] cspList;
    }
}

namespace B
{    
    enum Mode {};
    enum Creator {};

    class BTypeClass {}

    public partial class AddressList
    {
        int id;
        enum Mode mode;
        enum Creator creator
        long[] siteList;
        BTypeClass[] cspList;
    }
}

namespace C
{    
    enum Mode {};
    enum Creator {};

    class CTypeClass {}

    public partial class AddressList
    {
        int id;
        string name;
        enum Mode mode;
        enum Creator creator
        long[] siteList;
        CTypeClass[] cspList;
    }
}

I'll extend the partial class in namespace A with a new method:

namespace A
{
    public partial class AddressList
    {
        public T.AddressList ToPrivateAddressList<T>()
        {
            T.AddressList privAddrList = new T.AddressList();

            privAddrList.creator = (T.Creator)this.creator;
            privAddrList.id = this.id;
            privAddrList.name = this.name;
            privAddrList.mode = (T.Mode)this.mode;

            if (this.siteList != null && this.listType == Mode.XDAddressingModeSiteIDList)
            {
                privAddrList.siteList = new long[this.siteList.Length];
                Array.Copy(this.siteList, privAddrList.siteList, this.siteList.Length);
            }
            ...
        }
    }
}

Notice that part of the problem, in addition to the classes each part of a different namespace, are the enums that are also from the varying namespaces.

Finally, I envision calling it like so (though I know I can't actually do this, I'm looking for a solution that's roughly as elegant):

B.AddressList al1 = A.AddressList.ToPrivateAddressList<B>();
C.AddressList al1 = A.AddressList.ToPrivateAddressList<C>();

解决方案

I think what you are looking for is an interface and the where keyword in the generic type definition.

From your code I see that you have this:

  • a method that converts type A to type B
  • it does this by assigning properties with the same name
  • and then returns the new type B
  • the types can reside in different namespaces (but currently have the same name)
  • classes are partial

Instead of relying on the same name (which you can, using reflection you can achieve the effect you want), you should let each class implement an interface that contains the common properties. This way, you retain compile time type-safety:

public interface ICommonAddress 
{
    int id { get; set; }
    Mode mode { get; set; }
    Creator creator { get; set; }
    long[] siteList { get; set; }
    ICommonAddress CreateAddress();
}

You can now refactor your classes like this (of course, you'll have to change your fields into properties, but I'm assuming you have them as properties already:

// if your original partial class is auto-generated, it is ok to place 
// this definition in another file, it'll still work as long as 
// namespace, classname and compile-unit (must be in same project) are the same
public partial class AddressList : ICommonAddress
{
    int id { get; set; }
    Mode mode { get; set; }
    Creator creator { get; set; }
    long[] siteList { get; set; }
    ATypeClass[] cspList;

    ICommonAddress CreateAddress()
    {
        return new AddressList();   // NOTE: you can even have your ctor private!
    }
}

If you do that for each AddressList type you have, you can change your generic method as follows, and it will automatically work, including the IntelliSense showing you the common available properties. Also, implement it as an extension method, so that it applies to all your AddressList types (this is in your case better than using partial):

public T ToPrivateAddressList<T>(this ICommonAddress _this)
    where T: ICommonAddress
{
    T privAddrList = _this.CreateAddress();

    // this now works normally, without casting
    privAddrList.creator = _this.creator;
    privAddrList.id = _this.id;
    privAddrList.name = _this.name;
    privAddrList.mode = _this.mode;
}

Now, if you import a reference to this extension method, you can call ToPrivateAddressList() on any type that you have:

A.AddressList a_address = A.AddressList.CreateAddress();   // or new A.AddressList()
B.AddressList al1 = a_address.ToPrivateAddressList<B.AddressList>();
C.AddressList al1 = a_address.AddressList.ToPrivateAddressList<C.AddressList>();

这篇关于我怎么能传递一个命名空间的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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