简体   繁体   English

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

[英]Subclass needs to implement Interface property as static

My intent is that any API wrapper projects we write in the future around 3rd party or even internal APIs that need a session will need to (should by expected team pattern) implement this interface because it will enforce commonality in terms of those API Wrapper projects because I know that any session classes will always have GetCurrentSession, RenewSession, etc. in them...so we have a consistent pattern in terms of common members to be implemented for concrete session classes. 我的意图是我们将来围绕第三方编写的任何API包装器项目,甚至需要会话的内部API都需要(应该通过预期的团队模式)实现此接口,因为它将强制执行这些API Wrapper项目的通用性,因为我知道任何会话类总是会有GetCurrentSession,RenewSession等......所以我们在为具体会话类实现的通用成员方面有一致的模式。

So here's my interface: 所以这是我的界面:

/// <summary>
/// Represents an API end user based session
/// </summary>
public interface IAPISession
{
    #region Properties

    int SessionID { get; }

    /// <summary>
    /// Gets the user ID.
    /// Note: type string since userID is not always int in 3rd party APIs 
    /// </summary>
    /// <value>The user ID.</value>
    string UserID { get; }

    bool SessionHasExpired { get; }

    DateTime ExpirationDate { get; }

    void LogOut(); // expires the session & sets SessionHasExpired

    #endregion Properties

    #region Methods

    /// <summary>
    /// Renews the session by returning a brand new session 
    /// if the existing session has expired.
    /// </summary>
    /// <returns></returns>
    IAPISession RenewSession();


    /// <summary>
    /// Gets the current API session
    /// </summary>
    /// <returns></returns>
    IAPISession GetCurrentSession();

    #endregion Methods
}

Here is an implementation example: 这是一个实现示例:

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


    /// <summary>
    /// Gets the current API session singleton instance
    /// </summary>
    /// <returns></returns>
    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
        }
    }
}

and here's my problem. 这是我的问题。 A session is a singleton for the current user thread. 会话是当前用户线程的单例。 To access a singleton, that method GetCurrentSession() which I know all APIs we create will need to implement (will be totally different in HOW they will be implemented based on the API) I need the property to be a static property to get the singleton. 要访问单例,我知道我们创建的所有API都需要实现的GetCurrentSession()方法(将在HOW中完全不同,它们将基于API实现)我需要将属性作为静态属性来获取单例。

But you can't. 但你不能。 Because you can't have static members in an Interface. 因为您不能在接口中拥有静态成员。 So...yea I could take out the Interface pattern requirement but I really don't want to. 所以...是的,我可以拿出界面模式要求,但我真的不想。

FYI this is not functional code above, I'm doing my initial coding of all this and trying to design it best. 仅供参考,这不是上面的功能代码,我正在对所有这些进行初步编码并尝试最好地设计它。

UPDATE: 更新:

On the topic of factories, let me step back to give you more context in what I'm doing here. 关于工厂的话题,让我退后一步,为你提供更多关于我在这里所做的事情。 I needed to get the right custom APIService object (I create a service class for every API wrapper to work with) based on what API wrapper I'm coding for, so I created a GetService factory (or at least attempted to..have not done a lot of factories) like below. 我需要根据我正在编码的API包装器获取正确的自定义APIService对象(我为每个API包装器创建一个服务类),所以我创建了一个GetService工厂(或者至少尝试过...做了很多工厂)如下。 And in it you can see that all the methods are static, properties, etc. 在其中您可以看到所有方法都是静态的,属性等。

Usage example for below would be: 下面的用法示例是:

FacebookService service = PhotoServiceFactory.CurrentPhotoUploadServiceFactory;

Thoughts? 思考? I'm just trying to do the same for Session but feel I would like to actually expose the related session inside the Specific Service instance that I get back from the factory. 我只是想为Session做同样的事情,但我觉得我想实际公开我从工厂回来的特定服务实例中的相关会话。 So for instance I'd be able to do something like this: 所以例如我可以做这样的事情:

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

The service here is FacebookService type because the factory went out to get it based on the API type I'm working with (API type is an Enum I created that has values like Facebook, Flickr, etc.) 这里的服务是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
    }

Why do you need the property to be static to get the singleton? 为什么你需要属性是静态的来获得单身人士? An instance member can get at static members with no problem - it's the other way round that's tricky. 一个实例成员可以毫无问题地获得静态成员 - 这是另一回事,这很棘手。

// This should compile with no problems
public IAPISession GetCurrentSession()
{
    if (SessionHasExpired)
    {
        return null;
    }

    // TODO: return the singleton instance here...
}

If other code needs to get at the session statically, you could have another static member to do that. 如果其他代码需要静态获取会话,则可以使用另一个静态成员来执行此操作。

Admittedly it's a bit of a design smell for an instance member to only refer to static variables (any instance of FacebookSession will effectively have the same session, if you're on the same thread) but it should work. 不可否认,实例成员的设计气味只是引用静态变量( FacebookSession任何实例将有效地具有相同的会话,如果您在同一个线程上),但它应该有效。

You could try using Extension methods for interfaces to provide a common implementation for an interface method. 您可以尝试使用接口的扩展方法来为接口方法提供通用实现。 You could declare this extension method in the same namespace/assembly as the interface so that when someone references the interface, the extension method will be there already for them to use. 您可以在与接口相同的命名空间/程序集中声明此扩展方法,以便当有人引用该接口时,扩展方法将在那里供他们使用。 In that implementation, you could use your singleton and it would be a static. 在该实现中,您可以使用您的单例,它将是静态的。

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

You can convert the interface to a class, make it abstract, and make all those methods abstract too. 您可以将接口转换为类,使其成为抽象,并使所有这些方法也抽象化。 Then you can put whatever static fields you want in that abstract base class. 然后,您可以在该抽象基类中放置您想要的任何静态字段。

If the method is static, there's really no way to force children to implement it. 如果方法是静态的,那么实际上没有办法强迫孩子实现它。 If you think about how Interfaces are typically used, it makes more sense. 如果您考虑通常如何使用接口,则更有意义。 The typical use-case is something like: 典型的用例类似于:

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

My suggestion would be to create a Factory to get the different Singleton instances of IAPISession: 我的建议是创建一个Factory来获取IAPISession的不同Singleton实例:

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

I'm not 100% sure of what you're looking for but you can use statics with an interface. 我不是100%肯定你正在寻找什么,但你可以使用静态界面。 Instead using 而是使用

public static IAPISession GetCurrentSession()
{
    if (SessionHasExpired)
    {
        return null;
    }

    // TODO: return the singleton instance here...

}

To meet the interface definition you would implement this privately and expose it to the interface 要满足接口定义,您可以私下实现它并将其公开给接口

private static IAPISession GetTheCurrentSession()
{
    if (SessionHasExpired)
    {
        return null;
    }

    // TODO: return the singleton instance here...

}

public IAPISession GetCurrentSession()
{
return GetTheCurrentSession();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM