子类需要将Interface属性实现为static

我的意图是,我们将来围绕第三方编写的任何API包装器项目,甚至是需要会话的内部API都需要(应该通过预期的团队模式)实现此接口,因为它将强制执行这些API Wrapper项目的通用性,因为我知道任何会话类总是会有GetCurrentSession,RenewSession等……所以我们在为具体会话类实现的通用成员方面有一致的模式。

所以这是我的界面:

///  /// Represents an API end user based session ///  public interface IAPISession { #region Properties int SessionID { get; } ///  /// Gets the user ID. /// Note: type string since userID is not always int in 3rd party APIs ///  /// The user ID. string UserID { get; } bool SessionHasExpired { get; } DateTime ExpirationDate { get; } void LogOut(); // expires the session & sets SessionHasExpired #endregion Properties #region Methods ///  /// Renews the session by returning a brand new session /// if the existing session has expired. ///  ///  IAPISession RenewSession(); ///  /// Gets the current API session ///  ///  IAPISession GetCurrentSession(); #endregion Methods } 

这是一个实现示例:

 public class FacebookSession : IAPISession { private static FacebookSession _singletonInstance; private FacebookSession() { } #region Properties private HttpContext CurrentContext { get; set; } private HttpCookie CurrentSessionCookie { get; set; } #endregion #region IAPISession Members // Checks for a current session cookie public bool SessionHasExpired { get { return _singletonInstance == null; } } public IAPISession RenewSession() { throw new NotImplementedException(); } ///  /// Gets the current API session singleton instance ///  ///  public static IAPISession GetCurrentSession() { if (SessionHasExpired) { return null; } // TODO: return the singleton instance here... } public void LogOut() { throw new NotImplementedException(); } public int SessionID { get; private set; } public string UserID { get; private set; } public DateTime ExpirationDate { get; private set; } #endregion public void LogIn(HttpContext currentContext) { if (SessionHasExpired) { const string redirectUri = "http://localhost/Photo/FacebookOauth.aspx"; // page they will be redirected to after they auth string authUrl = ConfigUtil.GetAppConfigSetting("PayPalBaseUri") + "?client_id=" + ConfigUtil.GetAppConfigSetting("PayPalClientID") + "&redirect_uri=" + redirectUri; CurrentContext.Response.Redirect(authUrl); // redirect them to log in } } } 

这是我的问题。 会话是当前用户线程的单例。 要访问一个单例,我知道我们创建的所有API都需要实现的GetCurrentSession()方法GetCurrentSession()在HOW中它们将基于API实现完全不同)我需要将属性作为静态属性来获取单例。

但你不能。 因为您不能在接口中拥有静态成员。 所以…是的,我可以拿出界面模式要求,但我真的不想。

仅供参考,这不是上面的function代码,我正在对所有这些进行初步编码并尝试最好地设计它。

更新:

关于工厂的话题,让我退后一步,为你提供更多关于我在这里所做的事情。 我需要根据我正在编码的API包装器获取正确的自定义APIService对象(我为每个API包装器创建一个服务类),所以我创建了一个GetService工厂(或者至少尝试过…做了很多工厂)如下。 在其中您可以看到所有方法都是静态的,属性等。

下面的用法示例是:

 FacebookService service = PhotoServiceFactory.CurrentPhotoUploadServiceFactory; 

思考? 我只是想为Session做同样的事情,但我觉得我想实际公开我从工厂回来的特定服务实例中的相关会话。 因此,举例来说,我可以做这样的事情:

 service.CurrentSession which would give me the current facebook singleton session. 

这里的服务是FacebookService类型,因为工厂根据我正在使用的API类型出去获取它(API类型是我创建的具有Facebook,Flickr等值的Enum)

  public class PhotoServiceFactory { private static PhotoServiceFactory _singletonInstance; private PhotoServiceFactory(){} #region Properties public static PhotoUploadServiceFactory CurrentPhotoUploadServiceFactory { get { _singletonInstance = _singletonInstance ?? (_singletonInstance = new PhotoUploadServiceFactory()); return _singletonInstance; } } #endregion #region Methods public static IAPIService GetAPIService(APIType apiType) { IAPIService apiService = null; switch (apiType) { // return the right service singleton instance // based on the API type that we're working with case APIType.Facebook: apiService = FacebookAPIService.CurrentFacebookAPIService; break; case APIType.Flickr: apiService = null; // service not implemented break; case APIType.PhotoBucket: apiService = null; // service not implemented break; case APIType.Picasa: apiService = null; // service not implemented break; case APIType.Kodak: apiService = null; // service not implemented break; } return apiService; } #endregion } 

为什么你需要属性是静态的才能得到单身人士? 一个实例成员可以在没有问题的情况下获得静态成员 – 这是另一种方法,这很棘手。

 // This should compile with no problems public IAPISession GetCurrentSession() { if (SessionHasExpired) { return null; } // TODO: return the singleton instance here... } 

如果其他代码需要静态获取会话,则可以使用另一个静态成员来执行此操作。

不可否认,实例成员的设计气味只是引用静态变量( FacebookSession任何实例都会有效地拥有相同的会话,如果你在同一个线程上),但它应该有效。

您可以尝试使用接口的扩展方法来为接口方法提供通用实现。 您可以在与接口相同的命名空间/程序集中声明此扩展方法,以便当有人引用该接口时,扩展方法将在那里供他们使用。 在该实现中,您可以使用您的单例,它将是静态的。

 public interface IAPIWrapper { string UserID { get; } bool SessionHasExpired { get; } DateTime ExpirationDate { get; } void LogOut(); // expires the session & sets SessionHasExpired IAPISession RenewSession(); IAPISession GetCurrentSession(); } public static class IAPIWrapperImpl { private static Session session = new Session(); // Instantiate singleton here // This is an extension method for the IAPISession RenewSession method // the this keyword before the first parameter makes this an extension method public static IAPISession RenewSession(this IAPIWrapper wrapper) { // implementation details // use session here } // This is an extension method for the IAPISession GetCurrentSession method // the this keyword before the first parameter makes this an extension method public static IAPISession GetCurrentSession(this IAPIWrapper wrapper) { // implementation details // use session here } } 

您可以将接口转换为类,使其成为抽象,并使所有这些方法也抽象化。 然后,您可以在该抽象基类中放置您想要的任何静态字段。

如果方法是静态的,那么实际上没有办法强迫孩子实现它。 如果您考虑通常如何使用接口,则更有意义。 典型的用例类似于:

 var myInterfaceInstance = new SomeClassThatImplementsInterface(); myInterfaceInstance.InterfaceMethod(); 

我的建议是创建一个Factory来获取IAPISession的不同Singleton实例:

 public class IAPISessionFactory { public static IAPISession GetInstance() where T : IAPISession { if(typeof(T) == typeof(ConcreteSession) return ConcreteSession.GetInstance(); } } 

我不是100%肯定你在寻找什么,但你可以使用静态界面。 而是使用

 public static IAPISession GetCurrentSession() { if (SessionHasExpired) { return null; } // TODO: return the singleton instance here... } 

要满足接口定义,您可以私下实现它并将其公开给接口

 private static IAPISession GetTheCurrentSession() { if (SessionHasExpired) { return null; } // TODO: return the singleton instance here... } public IAPISession GetCurrentSession() { return GetTheCurrentSession(); }