2009-06-22 3 views
0

Я несколько дней царапаю голову над этим, и я до сих пор не понимаю, как реализовать этот интерфейс.Внедрение интерфейса в коде

Вот мой код:

namespace ConsoleApplication32 { 
public static class ScanAndSerialize 
{ 

    public static void Serialize() 
    { 

     List<string> dirs = FileHelper.GetFilesRecursive("s:\\"); 
     List<string> dirFiles = new List<string>(); 
     foreach (string p in dirs) 
     { 
      string path = p; 
      string lastAccessTime = File.GetLastAccessTime(path).ToString(); 
      bool DirFile = File.Exists(path); 
      DateTime lastWriteTime = File.GetLastWriteTime(p); 
      //dirFiles.Add(p + " , " + lastAccessTime.ToString() + " , " + DirFile.ToString() + " , " + lastWriteTime.ToString()); 
      dirFiles.Add(p); 
      dirFiles.Add(lastAccessTime); 
      dirFiles.Add(DirFile.ToString()); 
      dirFiles.Add(lastWriteTime.ToString()); 
      dirFiles.Add(Environment.NewLine); 

     } 


     XmlSerializer SerializeObj = new XmlSerializer(dirFiles.GetType()); 
     string sDay = DateTime.Now.ToString("MMdd"); 
     string fileName = string.Format(@"s:\project\{0}_file.xml", sDay); 
     TextWriter WriteFileStream = new StreamWriter(fileName); 

     SerializeObj.Serialize(WriteFileStream, dirFiles); 
     WriteFileStream.Close(); 


    } 

    static class FileHelper 
    { 
     public static List<string> GetFilesRecursive(string b) 
     { 
      // 1. 
      // Store results in the file results list. 
      List<string> result = new List<string>(); 

      // 2. 
      // Store a stack of our directories. 
      Stack<string> stack = new Stack<string>(); 

      // 3. 
      // Add initial directory. 
      stack.Push(b); 

      // 4. 
      // Continue while there are directories to process 
      while (stack.Count > 0) 
      { 
       // A. 
       // Get top directory 
       string dir = stack.Pop(); 

       try 
       { 
        // B 
        // Add all files at this directory to the result List. 
        result.AddRange(Directory.GetFiles(dir, "*.*")); 

        // C 
        // Add all directories at this directory. 
        foreach (string dn in Directory.GetDirectories(dir)) 
        { 
         stack.Push(dn); 
        } 
       } 
       catch 
       { 
        // D 
        // Could not open the directory 
       } 
      } 
      return result; 
     } 
    } 



    public class MyInterface: IValidationRowSet 
    { 

     public int RowNumber { get; set; } 

     public string RowAsString { get; set; } 
     public IValidationRowSet MatchedRow { get; set; } 
     public string FriendlyNameLabel { get; set; } 
     public string KeyFieldLabel { get; set; } 
     IList<string> lst = new List<string>(); 
     public string SourceWorksheetName { get; set; } 
     public string SourceRangeName { get; set; } 
     //public string SourceRangeName { get; set; } 
     public bool bReported { get; set; } 

     public int FieldCount { get { return lst.Count; } } 
     public string FieldData(int id) 
     { 
      if (id <= lst.Count) 
       return lst[id]; 
      else 
       return null; 
     } 
     public string ValidationMessage { get; set; } 




    } 

Вот объяснение интерфейса (до сих пор ломают голову над этим один)

namespace Validation { 
/// <summary> 
/// Implement this interface if you want the engine to callback when it finds exception 
/// messages. You will pass a reference to you class to the validation engine, and 
/// it will call "PostValidationMessage" for each exception example, including the message, 
/// the entire row set of data (vr), and the id of the field that created the exception. 
/// </summary> 
public interface IValidationReporter 
{ 
/// <param name="sMsg"></param> 
/// <param name="vr"></param> 
/// <param name="id"></param> 
    void PostValidationMessage(string sMsg, IValidationRowSet vr, int id); 
} 


/// <summary> 
/// Implement this interface in order to use the validation engine. 
/// The validation engine takes 2 IList<IValidationRowSet> objects and compares them. 
/// A class that implements this interface will contain an entire row of data that you'll 
/// want to compare. 
/// </summary> 
public interface IValidationRowSet 
{ 

    /// <summary> 
    /// should return an int of the number of fields in this row 
    /// </summary> 
    int FieldCount { get; } 

    /// <summary> 
    /// should return an int of the row number that this row is in the set 
    /// usually set when the data is assembled 
    /// </summary> 
    int RowNumber { get; set; } 

    /// <summary> 
    /// this is a function that should return the field data for this row at zero-indexed location "id" 
    /// ex: if the row contains this data: smith|fred|2126782524|[email protected]| 
    /// a call on this method of FieldData(2) will return the phone number 2126782524 
    /// </summary> 
    /// <param name="id"></param> 
    /// <returns></returns> 
    string FieldData(int id); 

    /// <summary> 
    /// this will be modified by the validation process 
    /// </summary> 
    string ValidationMessage { get; set; } 

    /// <summary> 
    /// this will be modified by the validation process 
    /// </summary> 
    IValidationRowSet MatchedRow { get; set; } 

    /// <summary> 
    /// returns a string that uniquely identifies this row 
    /// ex: if the row contains this data: smith|fred|2126782524|[email protected]| 
    /// so for this example, the unique identifier could be the email address [email protected] 
    /// </summary> 
    string KeyFieldLabel { get; set; } 

    /// <summary> 
    /// returns a string with the "friendly" name of this row 
    /// ex: if the row contains this data: smith|fred|2126782524|[email protected]| 
    /// so for this example, FriendlyNameLabel could be the name, such as "Fred Smith" 
    /// </summary> 
    string FriendlyNameLabel { get; set; } 

    /// <summary> 
    /// returns all fields in the row as pipe delimited 
    /// ex: 1,234.23|Fred Smith|[email protected]| 
    /// </summary> 
    string RowAsString { get; set; } 


    /// <summary> 
    /// if this is an excel file comparison, this should return the name 
    /// of the worksheet from whence this data came 
    /// </summary> 
    string SourceWorksheetName { get; set; } 


    /// <summary> 
    /// if this is an excel file comparison, this should return the name 
    /// of the worksheet range from whence this data came 
    /// </summary> 
    string SourceRangeName { get; set; } 

    /// <summary> 
    /// this will be modified by the validation process 
    /// </summary> 
    bool bReported { get; set; } 
} 
} 

Я читал многочисленные статьи/книги/проводки на форуме о Интерфейсы. Эта концепция кажется мне черной дырой ... и я нахожусь в проекте, где я должен это реализовать. Кто-нибудь знает, как вы это реализуете? Кстати - я ПОЛНЫЙ программист новичка ... менее 2 месяцев опыта ... поэтому, пожалуйста, не наказывай меня за мою зелень, пожалуйста.

Заранее спасибо.

+0

благодарит всех за то, что помог мне понять, что и как интерфейс, и что он делает немного лучше :) Кто-нибудь знает, как именно реализовать этот конкретный интерфейс в моем проекте? У меня есть нулевая помощь здесь на работе, к сожалению, и огромный хруст времени. – yeahumok

+0

Где вы точно застряли? Вы должны закончить то, что вы начали с FieldData и FieldCount - реализовать * все * методы. Например, RowNumber может просто вернуть частное целое поле («return rowNo;»}, а RowAsString должно быть конкатенированной строкой, как описано в комментарии. – Groo

ответ

3

Рассмотрите интерфейсы как прототип или шаблон для загадки, который нужно заполнить - подумайте о них как о белом пространстве и о строках, где нужно положить куски. Вам нужно будет вывести интерфейсы в конкретные классы - красивую головоломку.

Позвольте мне сохранить это, и я приведу пример.

interface IFoo 
{ 
    bool DoFoo(int number); 
} 

class Foo : IFoo 
{ 
    public bool DoFoo(int number) { 
     return (number++ >= 0); 
    } 
} 

class Foo2 : IFoo 
{ 
    public bool DoFoo(int number) { 
     return (number-- >= 0); 
    } 
} 

Теперь, когда у меня есть это, я могу делать такие вещи.

IFoo foo; 

if (!value) 
    foo = new Foo(); 
else 
    foo = new Foo2(); 

bool value2 = foo.DoFoo(27); 

Заметьте, я не могу сделать это с интерфейсами:

// WRONG 
Foo2 foo2 = new Foo(); 

Так что в основном подводит итог, что делает интерфейс и как он работает. Теперь ваша работа заключается в реализации этих конкретных реализаций интерфейса.

+0

Я думаю, он знает, что такое интерфейс. По крайней мере - теоретически. :) –

+0

Правда, но он говорит, что это «черная дыра»/ –

+0

, когда я намеревался, что это похоже на «черную дыру», было то, что до этой публикации у меня было мало понимания из того, что я читал как ПОЧЕМУ на земле кто-нибудь будет использовать это ... Более того, реализация большинства онлайн-примеров, которые я увидела, была простой мелочью, которая не помогала в более сложных реализациях. так жаль, если моя новизна кого-то обижает здесь. – yeahumok

0

Если вы используете визуальную студию, просто напишите «public class foo: IValidationRowSet». Затем нажмите foo с левым щелчком, затем сдвиньте + alt + f10, вниз, введите. Это создаст заглушку для реализации интерфейса.

И не называйте класс «MyInterface», это сбивает с толку. Это реализация интерфейса, а не самого интерфейса. :)

0

Трудно сказать, где ваш ум застрял с интерфейсами.

Интерфейсы - это абстрактное понятие. Не только буквально, но и в природе в том, что абстрактные классы и интерфейсы не могут быть созданы. Интерфейс еще более абстрактен, чем абстрактный класс, поскольку он не может содержать исполняемый код. Он устанавливает контракт между потребителем интерфейса и классом, который реализует интерфейс.

Теперь, если вы слышите полиморфизм, и вы начинаете царапать голову, тогда интерфейсы будут жесткой гайкой. Интерфейсы - один из распространенных способов введения полиморфизма в ваше приложение. У вас может быть множество реализаций IValidationReporter и IValidationRowSet. Поскольку вы отменили свои контракты, любой код, который может работать с этими абстракциями, сможет оставаться неизменным даже в тех случаях, когда вы переключаете реализации этих контрактов.

Ваш код реализует один из интерфейсов, но не другой.Также обратите внимание, что статические конструкции не могут быть выражены в контрактах (интерфейсах)

+0

Я считаю, что это совсем не сложно, просто требует некоторой практики. :) –

1

Как новый разработчик, я считаю, что лучший способ думать о интерфейсе как шаблоне, который включает в себя всю общедоступную информацию о классе (атрибуты, методы и т. д.) в качестве списка того, что должно быть создано для класса, реализующего его для выполнения работы, необходимой для этих методов и т. д.

Теперь должно быть множество людей, которые объяснят это намного лучше меня, и исправлять мои ошибки и, надеюсь, объяснять интерфейсы по-разному с статьями/книгами/публикациями таким образом, чтобы вы (и, надеюсь, я) могли понять :)

2

Вы можете себе представить, что интерфейс подобен список вопросов, на которые должен отвечать ваш класс. Таким образом, вы можете создать много классов, которые будут отвечать на эти вопросы по-другому.

Но для парня, который задает вопросы (который является ValidationReporter), будет важно получить ответы, а не тот, кто ответит на них.

a. Вам необходимо сообщить компилятору, что ваш класс реализует интерфейс

// my class implements the interface 
public class MyValidationRowSet : IValidationRowSet 

b. Вам необходимо реализовать каждый метод интерфейса. Это означает, что вам нужно убедиться, что каждый метод действительно что-то делает. В Visual Studio вы можете получить помощь, щелкнув правой кнопкой мыши по интерфейсу в строке выше и выбрав «Интерфейс реализации» из контекстного меню. Это создаст заглушки методов (пустые методы, которые вы можете заполнить).

public class MyValidationRowSet : IValidationRowSet 
{ 
    public int FieldCount 
    { 
     get 
     { 
      // return something 
     } 
    } 

    // you will need to implement each method from your 
    // interface in order to compile successfully 
} 

Я могу видеть из кода (public class MyInterface: IValidationRowSet), что вы не выполнили какой-либо метод - вы их оставили все пусто. Компилятор не позволит запустить программу, пока не будет уверен, что ваши методы возвращают правильные результаты.

c. Это в основном это. Как только вы пройдете точку a., Компилятор не позволит вам запустить программу, пока вы не внедрили все методы в этом интерфейсе. Когда вы закончите, вы можете создать новый экземпляр вашего класса, который может «дать ответы»:

// create a new instance of your class 
MyValidationRowSet instance = new MyValidationRowSet(); 
0

Не совсем уверен, что вы просите, но вот некоторые наблюдения:

общественности класс MyInterface: IValidationRowSet {...}

MyInterface не является «умным» именем для вашего класса, потому что это не интерфейс. Это фактическая реализация интерфейса. Я предлагаю вместо этого ValidationRowSetImpl или MyRowSet или аналогичный.

Кроме того, у вас есть

IList<string> lst = new List<string>(); 

застрял в середине вашей реализации интерфейса. Он должен быть явно упомянут как «частный», а по соображениям хорошей организации должен быть внизу вашего класса. Все методы из интерфейса должны быть вместе, в том же порядке, что и интерфейс. Вся используемая личная дата должна быть ниже этого.

+0

низ OR верх. Но будьте последовательны :) – flq

1

В качестве руководства для достижения прогресса я предлагаю жестко кодировать все методы, чтобы возвращать фиктивные данные, или бросать исключение Not Implemented.

Например:

RowNumber // Always returns 1 
RowAsString // return "FirstName,LastName,PhoneNumber" 
MatchedRow // throw exception 
FriendlyNameLabel // return "MyFriendlyRow" 
KeyFieldLabel// return "MyKeyField" 
SourceWorksheetName // return "DefaultWorksheet" 
SourceRangeName // return "DefaultRange" 
bReported // return true; 
FieldCount // return 3 (to match the number of fields indicated in RowAsString 
FieldData // simple switch/case: 0=>FirstName, 1=>lastName, 2=>PhoneNumber 
ValidationMessage // return "Data not validated" 

Это должно сделать код компиляции ... и, возможно, даже работать, то вы можете начать отладку, чтобы это выяснить, как предполагается, будет использоваться. Мало-по-маленькому, удалите «фиктивные» реализации и добавьте «настоящий» код.

Замечание: ваш начальный блок кода «ScanAndSerialize», похоже, не имеет отношения к IValidationRowSet. Есть ли связь, которую я пропускаю?

+0

Согласен, это хороший способ быстро запустить его. – Groo

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