Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-接口/抽象类-确保在方法上引发事件_C#_Events_Interface - Fatal编程技术网

C#-接口/抽象类-确保在方法上引发事件

C#-接口/抽象类-确保在方法上引发事件,c#,events,interface,C#,Events,Interface,我有一个定义为IStore的接口,有两种方法: public interface IStore<TEntity> { TEntity Get(object identifier); void Put(TEntity entity); } 公共接口晶体管 { TEntity-Get(对象标识符); 无效看跌期权(TEntity实体); } 我想举办一个关于Put成功的活动 (作为参考,Put可以在数据库中存储行,或在文件系统中存储文件等。) 因此,为产品类型实现Is

我有一个定义为IStore的接口,有两种方法:

public interface IStore<TEntity>
{
    TEntity Get(object identifier);
    void Put(TEntity entity);
}
公共接口晶体管
{
TEntity-Get(对象标识符);
无效看跌期权(TEntity实体);
}
我想举办一个关于Put成功的活动 (作为参考,Put可以在数据库中存储行,或在文件系统中存储文件等。)

因此,为产品类型实现Istore的类看起来有点像:

class MyStore : IStore<Product>
{
    public Product Get(object identifier)
    {
        //whatever
    }

    public void Put(Product entity)
    {
        //Store the product in db
        //RAISE EVENT ON SUCCESS
    }
}
public abstract class MyStoreBase : IStore<TEntity>
{
    public abstract TEntity Get(object identifier);

    public abstract void PutImpl(TEntity entity);

    public void Put(TEntity entity)
    {
        // Each inheritor will implement this method.
        PutImpl(entity);

        // But event is fired in base class.
        FireEvent();
    }
}
classmystore:IStore
{
公共产品获取(对象标识符)
{
//随便
}
公开作废认沽权(产品实体)
{
//将产品存储在数据库中
//举杯庆祝成功
}
}
我追求的是一种确保每一个IStore实现都会引发事件的方法-
我应该有一个抽象类,还是同时有一个接口?

是的,你应该使用一个抽象类而不是接口

如果您决定使用一个抽象类来实现您的接口,它不会阻止其他开发人员实现他们自己版本的接口,这最终不会引发事件

也就是说,即使使用抽象类也不会强迫其他开发人员使用您的方法,因为他们可能会覆盖它

我认为最好的方法是使用模板方法:

public abstract class AbstractStore<TEntity>
{
    public TEntity Get(object identifier);
    public sealed void Put(TEntity entity)
    {
        if (DoPut(entity))
        {
            // raise event
        }
    }

    protected abstract bool DoPut(TEntity entity);
}
公共抽象类AbstractStore
{
公共TEntity Get(对象标识符);
公开密封作废认沽权证(TEntity实体)
{
if(DoPut(实体))
{
//升起事件
}
}
受保护的抽象bool-DoPut(TEntity实体);
}

实际存储必须实现DoPut方法,返回一个布尔值,指示Put操作是否成功。事件将从Put方法引发,该方法是公开可见的。

确实无法确保IStore的每个实现都会引发事件。您可以有一个具有put方法的抽象类,但这并不意味着您可以在完全忽略抽象类方法的抽象类的子类中有一个put方法

最后,鼓励引发事件的最好方法是编写开发人员应该使用的方法,即抽象类。那样的话,他们就必须不遗余力地不使用它

我的建议:

public abstract class Store<TEntity>
{
    public abstract TEntity Get(object identifier);
    public void Put(TEntity entity)
    {
        //Do actions before call
        InternalPut(entity);
        //Raise event or other postprocessing
    }

    protected abstract void InternalPut(TEntity entity);
}
公共抽象类存储
{
公共抽象属性Get(对象标识符);
公开作废认沽权(可转让实体)
{
//在打电话之前做些什么
内部出售(实体);
//引发事件或其他后处理
}
受保护的抽象无效内部投入(潜在实体);
}

然后在类中重写
InternalPut

您需要让抽象类从接口实现Put方法。您还可以添加抽象方法,如PutImpl,如下所示:

class MyStore : IStore<Product>
{
    public Product Get(object identifier)
    {
        //whatever
    }

    public void Put(Product entity)
    {
        //Store the product in db
        //RAISE EVENT ON SUCCESS
    }
}
public abstract class MyStoreBase : IStore<TEntity>
{
    public abstract TEntity Get(object identifier);

    public abstract void PutImpl(TEntity entity);

    public void Put(TEntity entity)
    {
        // Each inheritor will implement this method.
        PutImpl(entity);

        // But event is fired in base class.
        FireEvent();
    }
}
公共抽象类MyStoreBase:IStore
{
公共抽象属性Get(对象标识符);
公开摘要无效(实体);
公开作废认沽权(可转让实体)
{
//每个继承器都将实现此方法。
Putinpl(实体);
//但事件是在基类中激发的。
firevent();
}
}

如果您确实需要使用接口,那么new可以执行方面继承。不幸的是,要获得该功能,您至少需要以200美元的价格购买个人许可证

有了这样一个方面,您将把它放在接口中声明的方法上,接口的所有实现都将继承它。

抽象类存储
 abstract class Store<TEntity>
{
     public abstract TEntity Get(object identifier);
     protected abstract void Put(TEntity entity);
     public void PutBase(TEntity entity)
     {
         Put(entity);
         //Raise event here
     }

}
{ 公共抽象属性Get(对象标识符); 受保护的抽象无效认沽权(TEntity实体); 公共数据库(TEntity实体) { 出售(实体); //在这里举行活动 } }

注意:我确实把它设置为受保护的,所以所有派生类都必须实现它,但是客户端代码不能调用它。

编写一个抽象类来包装一个
PutInner
-like方法绝对是最好的方法,正如其他人已经建议的那样

我只想补充一点,如果您想让
IStore
的任何实现在调用
Put
时始终引发事件,我还建议将所述事件添加到接口本身:

public interface IStore<TEntity>
{
    event EventHandler<EntityEventArgs<TEntity>> EntityAdded;

    TEntity Get(object identifier);
    void Put(TEntity entity);
}

public EntityEventArgs<TEntity> : EventArgs
{
    public TEntity Entity { get; set; }
}
公共接口晶体管
{
事件处理程序EntityAdded;
TEntity-Get(对象标识符);
无效看跌期权(TEntity实体);
}
公共实体EventArgs:EventArgs
{
公共tenty实体{get;set;}
}

这并不强迫实现者做任何事情;但它确实明确地建立了一种期望,即
EntityAdded
将在成功的
Put

中被提升,它也不会停止继承类来覆盖行为。没有真正的方法来保证这种行为。这将是我的答案。在某种程度上,当您允许重写方法时,您总是依赖于理解契约的人员。但是提供这样一个框架可以让你控制事情发生的顺序。