Переопределите конструктора по умолчанию частичного класса с другим частичным классом

Вот как я это делаю. Я сканирую все подпапки (подпакеты), и я не пытаюсь загружать анонимные классы:

   /**
   * Attempts to list all the classes in the specified package as determined
   * by the context class loader, recursively, avoiding anonymous classes
   * 
   * @param pckgname
   *            the package name to search
   * @return a list of classes that exist within that package
   * @throws ClassNotFoundException
   *             if something went wrong
   */
  private static List<Class> getClassesForPackage(String pckgname) throws ClassNotFoundException {
      // This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths
      ArrayList<File> directories = new ArrayList<File>();
      String packageToPath = pckgname.replace('.', '/');
      try {
          ClassLoader cld = Thread.currentThread().getContextClassLoader();
          if (cld == null) {
              throw new ClassNotFoundException("Can't get class loader.");
          }

          // Ask for all resources for the packageToPath
          Enumeration<URL> resources = cld.getResources(packageToPath);
          while (resources.hasMoreElements()) {
              directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8")));
          }
      } catch (NullPointerException x) {
          throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Null pointer exception)");
      } catch (UnsupportedEncodingException encex) {
          throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Unsupported encoding)");
      } catch (IOException ioex) {
          throw new ClassNotFoundException("IOException was thrown when trying to get all resources for " + pckgname);
      }

      ArrayList<Class> classes = new ArrayList<Class>();
      // For every directoryFile identified capture all the .class files
      while (!directories.isEmpty()){
          File directoryFile  = directories.remove(0);             
          if (directoryFile.exists()) {
              // Get the list of the files contained in the package
              File[] files = directoryFile.listFiles();

              for (File file : files) {
                  // we are only interested in .class files
                  if ((file.getName().endsWith(".class")) && (!file.getName().contains("$"))) {
                      // removes the .class extension
                      int index = directoryFile.getPath().indexOf(packageToPath);
                      String packagePrefix = directoryFile.getPath().substring(index).replace('/', '.');;                          
                    try {                  
                      String className = packagePrefix + '.' + file.getName().substring(0, file.getName().length() - 6);                            
                      classes.add(Class.forName(className));                                
                    } catch (NoClassDefFoundError e)
                    {
                      // do nothing. this class hasn't been found by the loader, and we don't care.
                    }
                  } else if (file.isDirectory()){ // If we got to a subdirectory
                      directories.add(new File(file.getPath()));                          
                  }
              }
          } else {
              throw new ClassNotFoundException(pckgname + " (" + directoryFile.getPath() + ") does not appear to be a valid package");
          }
      }
      return classes;
  }  
52
задан Elijah Manor 29 October 2008 в 18:02
поделиться

7 ответов

Это не возможно. Частичные классы являются по существу частями того же класса; никакой метод не может быть определен дважды или переопределен, и это включает конструктора.

Вы могли назвать метод в конструкторе, и только реализовать его в другом файле части.

39
ответ дан configurator 7 November 2019 в 19:09
поделиться

Я не совсем обращаюсь к OP, но если Вы, оказывается, генерируете классы с Реверсом EntityFramework ПОСТЕПЕННО Генератор, существует частичный метод, названный в конструкторе, который удобен для инициализации вещей, которые Вы добавляете через частичные классы самостоятельно...

Сгенерированный инструментом:

   [System.CodeDom.Compiler.GeneratedCode("EF.Reverse.POCO.Generator", "2.37.3.0")]
    public partial class Library {
        public string City { get; set; }
        public Library() {
            InitializePartial();
        }
        partial void InitializePartial();
    }

добавленный Вами:

    public partial class Library {
        List<Book> Books { get; set; }
        partial void InitializePartial() {
            Books = new List<Book>();
        }
    }

    public class Book {
        public string Title { get; set; }
    }
0
ответ дан 7 November 2019 в 09:09
поделиться
[

] У меня был похожий протест, мой сгенерированный код создавался dbml файлом (я использую классы Linq-to-SQL).[

] [

]В сгенерированном классе он вызывает частичную пустоту, называемую OnCreated() в конце конструктора. [

] [

]Короче говоря, если вы хотите сохранить важные вещи конструктора, которые сгенерированный класс делает для вас (что вы, вероятно, должны сделать), то в вашем частичном классе создайте следующее:[

] [
partial void OnCreated()
{
    // Do the extra stuff here;
}
]
68
ответ дан 7 November 2019 в 09:09
поделиться

Хммм, я думаю, что одним из элегантных решений было бы следующее:

//* AutogenCls.cs file
//* Let say the file is auto-generated ==> it will be overridden each time when
//* auto-generation will be triggered.
//*
//* Auto-generated class, let say via xsd.exe
//*
partial class AutogenCls
{
    public AutogenCls(...)
    {
    }
}



//* AutogenCls_Cunstomization.cs file
//* The file keeps customization code completely separated from 
//* auto-generated AutogenCls.cs file.
//*
partial class AutogenCls
{
    //* The following line ensures execution at the construction time
    MyCustomization m_MyCustomizationInstance = new MyCustomization ();

    //* The following inner&private implementation class implements customization.
    class MyCustomization
    {
        MyCustomization ()
        {
            //* IMPLEMENT HERE WHATEVER YOU WANT TO EXECUTE DURING CONSTRUCTION TIME
        }
    }
}

Этот подход имеет некоторые недостатки (как и все):

  1. Неясно, когда именно будет выполнен конструктор MyCustomization внутренний класс на протяжении всей процедуры построения класса AutogenCls.

  2. Если потребуется реализовать интерфейс IDiposable для класса MyCustomization, чтобы правильно обрабатывать удаление неуправляемых ресурсов класса MyCustomization, я не знаю (пока), как запустить метод MyCustomization.Dispose (), не касаясь AutogenCls .cs файл ... (но, как я сказал «пока» :)

Но этот подход предлагает отличное разделение от автоматически сгенерированного кода - вся настройка разделена в другом файле кода src.

наслаждайтесь :)

13
ответ дан 7 November 2019 в 09:09
поделиться

Вы не можете сделать этого. Я предлагаю использовать частичный метод, для которого можно тогда создать определение. Что-то как:

public partial class MyClass{ 

    public MyClass(){  
        ... normal construction goes here ...
        AfterCreated(); 
    }

    public partial void OnCreated();
}

Остальные должны быть симпатичны сам объяснительный.

РЕДАКТИРОВАНИЕ:

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

2
ответ дан jonnii 7 November 2019 в 19:09
поделиться

Ничто, о чем я могу думать. "Лучшим" путем я могу придумать, должен добавить ctor с фиктивным параметром и использованием что:

public partial class MyWebService : System.Web.Services.Protocols.SoapHttpClientProtocol 
{
   public override MyWebService(int dummy) 
   { 
         string myString = "overridden constructor";
         //other code...
   }
}


MyWebService mws = new MyWebService(0);
-1
ответ дан James Curran 7 November 2019 в 19:09
поделиться

Я думаю, что Вы могли бы быть в состоянии сделать это с PostSharp, и похоже, что кто-то сделал, что Вы хотите для методов в сгенерированных частичных классах . Я не знаю, переведет ли это с готовностью в способность записать, что метод и иметь его тело заменяет конструктора, поскольку я еще не дал ему выстрел, но это кажется стоящим того, чтобы попытаться.

Редактирование: это в том же направлении и также выглядит интересным.

2
ответ дан cfeduke 7 November 2019 в 19:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: