2012-01-15 4 views
1

У меня есть интерфейс, который используется несколькими классами, и реализация интерфейса одинакова для всех классов. Я бы сделал его базовым абстрактным классом, но потом он прекратил бы извлечение классов из наследования из другого класса позже, что мне нужно. Поэтому вместо того, чтобы переопределять один и тот же интерфейс во всех классах, могу ли я каким-то образом реализовать интерфейс в одном месте, например .h-файл, и включить файл .h в файл cs, чтобы класс «реализовал» интерфейс.Можно ли реализовать интерфейс в C# в файле .h?

Кстати, интерфейс состоит в основном из свойств и изменен на делегатов.

+3

У меня нет времени, чтобы написать реальный ответ, но интерфейсы могут иметь методы расширения. Это может соответствовать тому, что вы ищете, но это зависит от того, что вы пытаетесь сделать. –

+0

@ 32bitkid Спасибо, я посмотрю. – mihajlv

+0

Если методы расширения не вырезают его в вашем случае, попробуйте разложить реализацию интерфейса в отдельный класс, который будет содержать ссылку на обернутый объект одного из ваших нескольких классов. В зависимости от того, что вы пытаетесь сделать, вы можете предоставить доступ к вашему обернутому объекту, например. через 'IServiceProvider'. –

ответ

1

Я немного ржавый на моей C#, так что, конечно, может быть C# -специфический способ сделать это. Однако в более общем смысле вы можете обеспечить реализацию в своем собственном файле стандартного класса. Для каждого класса, который должен реализовывать интерфейс, вам все равно нужно объявить методы интерфейса, но вместо того, чтобы в них были скопированы и вставлены длинные реализации, вы можете иметь однострочные вызовы для общей реализации «include».

(Это, вероятно, не будет лучшим решением, но должно быть работоспособным один, который мог бы по крайней мере, чтобы вы начали.)

+0

Я бы порекомендовал вам использовать структуру вместо класса, чтобы избежать дополнительного выделения. – chuckj

1

РЕДАКТИРОВАТЬ: Поцарапать все под строкой - согласно комментариям, это, вероятно, не то, что вы хотите.

К сожалению, mixins недоступны в качестве встроенной языковой функции в C#, кроме как с помощью некоторых сомнительных методов, включая инструменты для компиляции, такие как PostSharp. Некоторые инструменты IoC также могут создавать похожие на микширование вещи (см. Best implementation of INotifyPropertyChange ever).

К пункту @ 32bitkid вы можете написать extension methods. Они не являются интерфейсами, но они позволяют применять реализацию поведения к типу извне этого типа. Например, вы можете написать:

public static class IPersonExtensions { 
    // Note use of this keyword 
    public static Int32 GetAge(this IPerson p) { return DateTime.Now - p.BirthDate; } 
} 

затем использовать его таким образом:

var p = new Person(...); 
var pAge = p.GetAge(); 

Да, как интерфейсы, как правило, используется- хотя они получают .cs файлы, не .h файлы. Вы можете определить интерфейс в собственном файле, как класс, а затем объявить класс как реализацию интерфейса.

Например, в IFoo.cs:

public interface IFoo { 
    public String Bar { get; set; } 
} 

, а затем в ConcreteFoo.cs:

public class ConcreteFoo : IFoo { 
    // This property implements IFoo.Bar 
    public String Bar { get; set; } 
} 

(Это пример auto-implemented property кстати)

IFoo даже не обязательно должен быть в собственном файле - он может быть в любом файле .cs. По соглашению, он обычно находится в его собственном, хотя. Также обратите внимание на соглашение об использовании префикса I для интерфейсов.

Вы можете прочитать больше об этом, вот например: http://www.csharp-station.com/Tutorials/Lesson13.aspx

+1

Оператор хочет знать, как писать mixin, а не как использовать интерфейс в целом. –

+0

А, это другой шар воска ... редактирование ... –

1

C# не имеет понятия заголовочных файлов. Вы не можете сделать это легко в C#. Если вы реализуете интерфейс и хотите иметь одну и ту же реализацию в другом классе, тогда другой класс должен быть получен из класса реализации.

Пример:

public interface IFoo 
{ 
    void DoSomething(); 
} 

public class SomeClass : IFoo 
{ 
    public void DoSomething() 
    { 
    } 
} 

Если теперь вы хотите иметь SomeOtherClass, который имеет ту же реализацию, как SomeClass то вам необходимо получить SomeOtherClass из SomeClass или переописать его или передать вызов DoSomething к экземпляру SomeClass. Другой вариант - использовать такой инструмент, как DynamicProxy, который может поддерживать стили mixin.

0

Вам в основном требуется множественное наследование, которое C# не поддерживает, однако вы все равно можете использовать реализацию интерфейса в других классах, которые уже производятся из другого класса. Один из способов, которым я придумал, - использовать partial classes и T4 Text Templates. Это небольшой взлом, но это лучше, чем копировать/вставлять одну и ту же реализацию интерфейса во многих производных классах. Ниже приведен упрощенный пример:

IInterface.cs

public interface IInterface 
{ 
    void Foo(); 
} 

InterfaceImpl.cs

public partial class InterfaceImpl : IInterface 
{ 
    public void Foo() 
    { 
     Console.WriteLine("Foo"); 
    } 
} 

BaseClass.cs

using System; 

public class BaseClass 
{ 
    public void Bar() 
    { 
     Console.WriteLine("Bar"); 
    } 
} 

DerivedClassA.cs

public partial class DerivedClassA : BaseClass, IInterface 
{ 
    public void FooBar() 
    { 
     this.Foo(); 
     this.Bar(); 
    } 
} 

DerivedClassAInterfaceImpl.tt

<#@ template debug="false" hostspecific="true" language="C#" #> 
<#@ output extension=".cs" #> 
<# var codeText = System.IO.File.ReadAllText(this.Host.ResolvePath("InterfaceImpl.cs")).Replace("InterfaceImpl", "DerivedClassA"); #> 
<#= codeText #> 

DerivedClassB.cs

public partial class DerivedClassB : BaseClass, IInterface 
    { 
     public void BarFoo() 
     { 
      this.Bar(); 
      this.Foo(); 
     } 
    } 

DerivedClassBInterfaceImpl.tt

<#@ template debug="false" hostspecific="true" language="C#" #> 
<#@ output extension=".cs" #> 
<# var codeText = System.IO.File.ReadAllText(this.Host.ResolvePath("InterfaceImpl.cs")).Replace("InterfaceImpl", "DerivedClassB"); #> 
<#= codeText #> 

Это немного раздражает, что это требует создания файла Tt для каждого производного класса, который хочет для использования реализации интерфейса, но он по-прежнему сохраняет код копирования/вставки, если InterfaceImpl.cs - это больше, чем несколько строк кода. Также возможно просто создать один файл tt и указать имя всех производных частичных классов и сгенерировать multiple files.

Смежные вопросы