如何将命名空间传递给方法?

时间:2012-03-30 18:27:35

标签: c#

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);
        }
        ...

最初编写的目的是将SOAP名称空间MyOldService中定义的列表复制到新名称空间MyNewService中的相同布局的类中。问题是,对于soap类,如果我将MyOldService命名空间导入第三个命名空间,比如说MyOtherAppService,那么我的AddressList类就会成为第三个命名空间的成员并被引用。

因此,我不是要复制代码,而是想用类似于泛型的东西来装饰它(或以某种方式调整它)(我理解它不会起作用,因为我改变了名称空间,不只是一个固定类型[我需要从每个命名空间中有多种类型,从代码片段中可以看出])允许它将地址列表转换为需要的任何命名空间中的相应类。可能的?

修改:在回复下面的一些评论时,我会尝试定义一个更好的例子,说明我尝试做的事情。

通过Web引用从WSDL导入的三个类(不,这些不会编译,只是用于说明的示例)。类AddressList都具有相同的布局。

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;
    }
}

我将使用新方法扩展命名空间A中的分部类:

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);
            }
            ...
        }
    }
}

请注意,除了不同命名空间的每个部分的类之外,问题的一部分是来自不同命名空间的枚举。

最后,我设想这样称呼它(虽然我知道我实际上可以做到这一点,但我正在寻找一种优雅的解决方案):

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

3 个答案:

答案 0 :(得分:0)

如果我对您的问题不满意

namespace A
{
    public class MyClass {... }
}

namepsace B
{  
   public class MyClass {...}
}

您的问题是:我如何定义在同一函数中有时会处理A.MyClass和其他情况B.MyClass的“通用”内容。

如果您考虑名称空间类似于类型定义的一部分,我认为这个故事就变得清晰了。 就像你有两种不同的类型,并希望有一个适用于它们的通用。该通用类知道何时选择A.MyClass方法,以及何时选择B.MyClass方法。

如果不是您所要求的,请澄清。

答案 1 :(得分:0)

您是否在询问如何执行此操作:

namespace Old
{
  public New.Address Foo()
  {
    New.Address result;
    //...
    return result;
  }
}

无需说'新'。&#39;每次出现地址?但是,如果您不这样做,代码会使用Old.Address

您可以从此项目的构建/链接中删除Old.Address(使用此代码)吗?

答案 2 :(得分:0)

我认为你要找的是接口和泛型类型定义中的where关键字。

从你的代码我看到你有这个:

  • 将类型A转换为类型B的方法
  • 通过分配具有相同名称的属性
  • 来实现此目的
  • 然后返回新类型B
  • 类型可以驻留在不同的名称空间中(但目前具有相同的名称)
  • 班级为partial

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

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

您现在可以像这样重构您的类(当然,您必须将您的字段更改为属性,但我假设您已将它们作为属性:

// 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!
    }
}

如果对每个AddressList类型执行此操作,则可以按如下方式更改通用方法,它将自动运行,包括显示常用属性的IntelliSense。此外,将其实现为扩展方法,以便它适用于您的所有AddressList类型(在您的情况下比使用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;
}

现在,如果您导入对此扩展方法的引用,则可以在您拥有的任何类型上调用ToPrivateAddressList()

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>();