2015-12-23 17 views
10

Tôi muốn thêm giao diện vào một số loại được cài sẵn. Tôi có một giao diện, IConcludable, mà tôi đang sử dụng như một ràng buộc cho Conclusion<T>. Tôi không có đầu mối làm thế nào để tiếp cận điều này, hoặc nếu nó thậm chí có thể.Có cách nào để mở rộng kiểu tích hợp để kế thừa giao diện không?

Basic Layout

public interface IConcludable { } 

public struct Conclusion<T> where T : IConcludable 
{ 
    public bool IsSuccessful; 
    public T Result; 

    // Constructors, members, etc. 
} 

public class ErrorReport : IConcludable { ... } 

public class MathArg : IConcludable { ... } 

public class ParseResult : IConcludable { ... } 

Thực hiện

public Conclusion<ParseResult> ParseInput (string input) 
{ 
    // Parse input... 
    // Initialize ParseResult object... 

    return new Conclusion<ParseResult>(result); 
} 

Vấn đề

Khi tôi nhận được giá trị cuối cùng, đó là một built-in loại như int, double, string, bool, vv Tôi muốn sử dụng Conclusion<T> như quay trở lại bởi vì tôi có một lớp học để xử lý các báo cáo lỗi khi chuỗi đầu vào là không hợp lệ:

if (conclusion.ReturnObject is ErrorReport) 
{ 
    ErrorManager errorManager = new ErrorManager(); 
    errorManager.Resolve(conclusion); 
} 

Nghiên cứu

Tôi nhìn vào Các ràng buộc .

Dường như những hạn chế chỉ gắn với nhau, vì vậy kể cả các giao diện của mỗi built-in loại mà tôi cần đòi hỏi phải xác định một núi các phương pháp mà không có bất cứ điều gì để làm với tôi Conclusion struct.


phương pháp mở rộng

Những thực sự thay đổi hành vi của các loại built-in. Nó không phải là những gì tôi đang tìm kiếm vì giao diện của tôi, IConcludable, không có bất kỳ phương pháp nào.

Thay built-in loại

Không thể. Tôi không cần phải thay đổi hành vi của các loại này. Tôi chỉ muốn thêm một giao diện trống vào nó.

Dường như không có bất kỳ điều gì liên quan đến việc thêm giao diện vào loại được cài sẵn. Tôi không chắc chắn nếu "Thừa kế" là những gì nó sẽ được đề cập đến. Điều này có thể không?

Sửa

Better giải thích về Kết luận struct

Tôi đang sử dụng các cấu trúc kết luận như một đối tượng trở lại trong hầu hết các phương pháp của tôi. Điều này là do tôi đang sử dụng các đại biểu. Xem mã thực tế của các đối tượng bên dưới:

public delegate Conclusion<T> Validator<T>(T subclass) where T : IVerifiable<T>; 

public delegate Conclusion<BaseFunction> Executor(BaseFunction subclass); 

public struct Conclusion<T> where T : IConcludable 
{ 
    public bool IsSuccessful; 
    public T ReturnObject; 

    public Conclusion(T returnObject) 
    { 
     this.ReturnObject = returnObject; 
     this.IsSuccessful = returnObject is Error ? false : true; 
    } 
} 

public class BaseFunction : IVerifiable<BaseFunction>, IConcludable 
{ 
    public List<BaseArgument> Args; 
    public Executor Executing; 
    public Validator<BaseFunction> Validating; 
    public string UserInput; 

    public Conclusion<BaseFunction> Validate(BaseFunction subclass) 
    { 
     if (this.Validating != null) 
     { 
      return Validating(subclass); 
     } 
     else 
     { 
      StringBuilder message = new StringBuilder(); 
      message.Append("A Validating delegate has not been assigned."); 

      throw new InvalidOperationException(message.ToString()); 
     } 
    } 

    public Conclusion<BaseFunction> Execute(BaseFunction subclass) 
    { 
     if (this.Executing != null) 
     { 
      return this.Executing(subclass); 
     } 
     else 
     { 
      StringBuilder message = new StringBuilder(); 
      message.Append("An Executing delegate has not been assigned."); 

      throw new InvalidOperationException(message.ToString()); 
     } 
    } 
} 

public class Function<T> : BaseFunction 
{ 
    public T Result; 

    public Function() 
    { 
     base.Args = new List<BaseArgument>(); 
    } 
} 

public class BaseArgument : IVerifiable<BaseArgument>, IConcludable 
{ 
    public string Role; 
    public string UserInput; 
    public int Position; 
    public Validator<BaseArgument> Validating; 

    public Conclusion<BaseArgument> Validate(BaseArgument subclass) 
    { 
     if (this.Validating != null) 
     { 
      return Validating(subclass); 
     } 
     else 
      throw new InvalidOperationException(); 
    } 
} 

public class Argument<T> : BaseArgument 
{ 
    public T Value; 

    public Argument(int position) 
    { 
     base.Position = position; 
    } 
} 

public static class ExecutionHandler 
{ 
    public static Conclusion<BaseFunction> Sum(BaseFunction subclass) 
    { 
     subclass = (Function<double>)subclass; 

     // Execution code. 

     return new Conclusion<BaseFunction>(subclass); 
    } 

    public static Conclusion<BaseFunction> Concatenate(BaseFunction subclass) 
    { 
     subclass = (Function<double>)subclass; 

     // Execution code. 

     return new Conclusion<BaseFunction>(subclass); 
    } 
} 

Nếu tôi cần đăng nhiều hơn, tôi sẽ làm như vậy. nhưng nó thực sự rất nhiều để xem xét. Kiểu trả về của các phương thức được gán bởi tất cả các đại biểu mà tôi sử dụng có kiểu trả về là Conclusion<T> để tôi có thể có một đối tượng trả về cũng như một lỗi nếu xảy ra. Các hàm trong mã ở trên trả về Conclusion<BaseFunction>, nhưng trở lại đó được chuyển đổi thành một đối tượng Addend<T> nếu nó là một số. Nếu nó là một phần của một loại hàm khác trả về một số string hoặc bool hoặc loại khác, nó sẽ được chuyển đổi thành một loại lớp khác. Khi kết thúc tính toán bằng số, lợi nhuận sẽ là một cái gì đó như Conclusion<int> hoặc Conclusion<double>. Vì vậy, hãy thêm intdouble vào giao diện IConcludable là những gì tôi đang cố gắng thực hiện. giải thích

Better của ứng dụng

Tôi viết một giao diện điều khiển ứng dụng C#. Nó lấy đầu vào từ người dùng và viết một câu trả lời. Dữ liệu nhập tương tự như công thức Excel: Sum(5, 15, Average(2, 3), 5) hoặc Concatenate("5 + 5 = ", Text(Sum(5, 5))). Chuỗi đầu vào được xác thực, phân tích cú pháp và trả về kết quả.

+0

như tôi thấy trong triển khai của bạn, bạn đang trả lại Kết luận . Nhưng bạn cũng nói *** Khi tôi nhận được giá trị cuối cùng, nó là một kiểu tích hợp như int, double, string, bool, etc ***, tôi không hiểu phần này. –

+0

Mặc dù câu hỏi của bạn được đặt rất tốt, tôi nghĩ bạn nên làm sắc nét * câu hỏi thực tế * bạn có, vì hiện tại nó không rõ ràng những gì không làm việc với cấu trúc này. –

+1

Không phải là kịch bản cho ** Mẫu bộ điều hợp **? –

Trả lời

1

CẬP NHẬT (ADD GIẢI THÍCH THÊM)

Theo yêu cầu, tôi muốn giải thích thêm một chút về câu trả lời cuối cùng của tôi.

Yêu cầu

  • Các Conclusion cần phải hỗ trợ cả hai giá trị loại và kiểu tham chiếu
  • Generic
  • loại Value: tất cả các loại dữ liệu số (int, ngắn, dài, vv), boolean, char, date ....
  • Loại tham chiếu: chuỗi và lớp do người dùng xác định (trong mẫu của OP, IConcludable)

Giải pháp:

  • giới thiệu một lớp cơ sở (AbstractConclusion) chấp nhận Object như là đầu vào chung
  • Di chuyển logic để lớp cơ sở để tái sử dụng
  • giới thiệu hai triển khai bê tông mới chấp nhận structIConcluable (có khả năng thêm triển khai khác, ví dụ: chuỗi)
  • Các lớp kế thừa có thể cho tất cả các phương pháp của lớp cơ sở

ORIGINAL ĐÁP:

Bạn có thể đặt logic trong AbstractConclusion lớp, và có hai hiện thực của nó (Conclusion mà chấp nhận IConcludeablePrimitiveConclusion mà chấp nhận loại struct dữ liệu)

Xem mẫu mã bên dưới:

void Main() 
{ 
    PrimitiveConclusion<int> primitiveConclusion = new PrimitiveConclusion<int>(1); 
    Conclusion<ParseResult> parseResultConclusion = new Conclusion<ParseResult>(new ParseResult {}); 

    Console.WriteLine($"{primitiveConclusion.Result.GetType()}"); 
    Console.WriteLine($"{parseResultConclusion.Result.GetType()}"); 
} 

public class TestClass 
{ 
    public Conclusion<ParseResult> ParseInput(string input) 
    { 
     return new Conclusion<ParseResult>(null); 
    } 
} 

public interface IConcludable { } 

public abstract class AbstractConclusion<T> 
{ 
    public AbstractConclusion(T t) 
    { 
     IsSuccessful = t != null; 
     Result = t; 
    } 
    public bool IsSuccessful; 
    public T Result; 
} 

public class Conclusion<T> : AbstractConclusion<T> where T : IConcludable 
{ 
    public Conclusion(T t) : base(t) 
    { 
    } 
} 


public class PrimitiveConclusion<T> : AbstractConclusion<T> where T : struct 
{ 
    public PrimitiveConclusion(T t) : base(t) 
    { 
    } 
} 


public class ParseResult : IConcludable { } 
+0

kienct89, tôi đang cố gắng hiểu những gì lớp trừu tượng đang làm. Có vẻ như nó sẽ chấp nhận bất kỳ giá trị nào. Giống như 'T' tương đương với' đối tượng'. Đó có phải là lớp trừu tượng trong ví dụ của bạn không? Cảm ơn. –

+0

@TylerPantuso: 'AbstractConclusion' chỉ là một lớp cơ sở để nhóm tất cả các chức năng tương tự của Kết luận, do đó bạn không cần phải viết lại cho tất cả các lớp con. Đối với phần thứ hai của câu hỏi của bạn, nó phải chấp nhận tất cả các loại (để hỗ trợ nguyên thủy, int và IConcluable). –

+0

Không thể loại bỏ 'IConcludable' hoàn toàn? –

0

Với where T : IConcludable ràng buộc loại chung chung, bạn không thể vượt qua int làm đối số chung. Và cũng không có cách nào để nối thêm một giao diện vào kiểu nguyên thủy.

Bạn có thể thực hiện một số cách giải quyết để thực hiện việc này. Bạn có thể đặt logic chính của Conclusion vào lớp cơ sở trừu tượng và kế thừa từ nó, tái cấu trúc Conclusion như class (vì struct s không hỗ trợ thừa kế) và tạo các lớp

public class Conclusion<T> : BaseConclusion 
where T : IConcludable 

public class PrimitiveConclusion<T> : BaseConclusion 
where T : struct 

và cũng có thể bạn nên tạo một lớp khác cho string, vì string không phải là cấu trúc và không triển khai IConcludable

Như tôi đã biết, có tôi s không có cách nào khác để vượt qua các loại khác nhau như các đối số chung chung.


Ngoài ra, thay vì tạo Conclusion lớp cho sẵn trong các loại bạn có thể tạo wrapper struct, mà sẽ thực hiện IConcludable. Và có một thỏa thuận với nó

public struct Wrapper<T> : IConcludable 
{ 
    public T Value { get; set; } 
} 
Các vấn đề liên quan