【问题标题】:How to use generic method to replace duplicated properties?如何使用泛型方法替换重复的属性?
【发布时间】:2011-07-29 19:56:05
【问题描述】:

目前我的代码具有以下属性:

  Private _queueRetriever As Services.IQueueRetriever
  Public ReadOnly Property QueueRetriever As Services.IQueueRetriever
     Get
        If _queueRetriever Is Nothing Then
           RemotingSetup.RegisterHttpBinaryChannel()
           _queueRetriever = RemotingFactory.CreateProxy(Of Services.IQueueRetriever)(Options.DevLocal)
        End If

        Return _queueRetriever
     End Get
  End Property

  Private _queueCountRetriever As Services.IQueueCounter
  Public ReadOnly Property QueueCounter As Services.IQueueCounter
     Get
        If _queueCountRetriever Is Nothing Then
           RemotingSetup.RegisterHttpBinaryChannel()
           _queueCountRetriever = RemotingFactory.CreateProxy(Of Services.IQueueCounter)(Options.DevLocal)
        End If

        Return _queueCountRetriever
     End Get
  End Property

如您所见,这两个属性的代码基本相同。只是种类不同。我在泛型方法方面不是很有经验,但我觉得我应该能够使用泛型使这段代码更DRY。可以做到吗?或者这不是泛型方法的工作?

编辑

基于 Marc 的回答,我想出了以下几点:

  Protected Services As New Dictionary(Of Type, Object)

  Protected Function CreateService(Of T)() As T
     If Not Services.ContainsKey(GetType(T)) Then

        RemotingSetup.RegisterHttpBinaryChannel()
        Services.Add(GetType(T), RemotingFactory.CreateProxy(Of T)(Options.DevLocal))

     End If

     Return DirectCast(Services(GetType(T)), T)
  End Function

当然可以这样使用:

Me.CreateService(Of IService).Foo()

【问题讨论】:

    标签: .net vb.net generics


    【解决方案1】:

    您可以这样做(并为切换到 C# 表示歉意,但我的 VB 技能在这里缺乏微妙之处 - 我确信它在 VB 中也可以正常工作)

    private T GetProxy<T>(ref T field) where T : class {
        if(field == null) {
            RemotingSetup.RegisterHttpBinaryChannel();
            field = RemotingFactory.CreateProxy<T>(Options.DevLocal);
        }
        return field;
    }
    

    与:

    private Services.IQueueCounter queueCounter;
    public Services.IQueueCounter QueueCounter {
        get { return GetProxy(ref queueCounter); }
    }
    private Services.IQueueRetriever queueRetriever;
    public Services.IQueueRetriever QueueRetriever {
        get { return GetProxy(ref queueRetriever); }
    }
    

    【讨论】:

    • 他有 240k+ 代表是有原因的。我想到了helper方法,没想到也用ref关键字覆盖了方法中字段的初始化。如果可以的话,我会投票 5 次。面对这种情况,我的建议显得苍白无力。
    • 酷!难道不能用一种可能维护实例化服务字典的方法来完全替换属性吗?
    • @TaylorOtwell 如果你愿意,可能
    • @Marc Gravell - 谢谢!你的例子让我足够接近我能够编写一个维护服务字典的方法。
    【解决方案2】:

    您可以创建一个私有泛型方法来返回适当的通道,但在这种情况下,您基本上会用 1 行代码和两行方法调用替换 2 行代码。这可能不值得付出努力,除非您添加第三种类型的频道,否则您将避免在第三种情况下忘记RemotingSetup.RegisterHttpBinaryChannel 行的危险。

    【讨论】:

      【解决方案3】:

      您不能在 .Net 中创建通用属性

      您可以做的是创建一个在 Get 中调用的通用方法:

        Private _queueCountRetriever As Services.IQueueCounter
        Public ReadOnly Property QueueCounter As Services.IQueueCounter
           Get
              Return MyGet(Of QueueCounter ,IQueueCounter )(_queueCountRetriever)
           End Get
        End Property
      
        Private Function MyGet(Of T As IT, IT)(ByRef propertyVar As T ) As IT
             If propertyVar Is Nothing Then
                 RemotingSetup.RegisterHttpBinaryChannel()
                 propertyVar = RemotingFactory.CreateProxy(Of IT)(Options.DevLocal)
              End If
        End Function
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-11
        • 1970-01-01
        • 1970-01-01
        • 2014-12-15
        • 2010-12-24
        相关资源
        最近更新 更多