1

I have an application which is quite mature. It contains an inheritance hierarchy to promote code re-use, and has worked perfectly for years until a couple of days ago. It works perfectly in the real world, but I am currently unable to design any form that inherits from one of the base forms.

Now, every time I try to design a form that inherits from MpvViewBase I get this error message:

Method 'CloseView' in type 'CommonForms.MvpViewBase' from assembly 'CommonForms, Version=1.0.6377.15105, Culture=neutral, PublicKeyToken=null' does not have an implementation.

Firstly, it does have an implementation or the code would not build which it does perfectly.

Secondly, the version number displayed is not the version number that applies to the dll.

Thirdly, the form is a component part of that dll so no external reference to it is required.

Things I have tried:

  1. Clean and rebuild
  2. Search for every CommonForms.dll on the computer and delete them
  3. Delete the component model cache
  4. Copy the minimum to a new solution

None of these have made any difference. I do not understand why this has occurred, since no change at the relevant level has been applied since 2012. However, it is a serious problem since I cannot design ANY forms that inherit from MpvViewBase - and almost any form in the solution that is more than a message dialog inherits from it!

Anybody got any suggestions as to where I might look next to resolve this issue?

Edit

As requested, below is the code for the base class and the first inheriting class. MvpViewBase opens in the Designer, ControllableViewBase and any form inherited from it fails to open:

MvpViewBase

public partial class MvpViewBase : MvpFormBase, IView
{

    #region Event Keys

    public EventKey<CancelEventArgs> CompleteRequested { get; private set; }
    public EventKey GenericChangeNotified{ get; private set; }
    public EventKey ShowHelpRequested{ get; private set; }

    #endregion

    #region Private Instance Members

    #endregion

    #region Protected Instance Memebers

    protected Size InitialSize;

    #endregion

    #region Constructors

    public MvpViewBase()
    {
        InitializeComponent();
        if (AppCommon.RunningFromVisualStudioDesigner)
        {
            return;
        }

        InitialiseLocal();
    }

    #endregion

    #region Form Events

    protected override void OnClosing(CancelEventArgs e)
    {
        var args = new CancelEventArgs();
        CompleteRequested.Raise(this, args);

        e.Cancel = args.Cancel;

        base.OnClosing(e);
    }

    private void MvpViewBaseLoad(object sender, EventArgs e)
    {
        FormControl.SetCharacterCase(this, (CharacterCasing) CompanySettings.Instance.CharacterCase);
        MinimumSize = InitialSize;
    }

    #endregion

    #region Methods

    ///<summary>
    /// Closes the form
    ///</summary>
    public void CloseView()
    {
        CloseView(MessageResult.None);
    }

    public void CloseView(MessageResult result)
    {
        if (InvokeRequired)
        {
            Invoke((MethodInvoker)(() => CloseView(result)));
            return;
        }

        if (result > MessageResult.None)
        {
            DialogResult = (DialogResult) result;
        }

        Close();
    }

    ///<summary>
    /// Displays a File Open dialog
    ///</summary>
    ///<param name="config">A FileOpenConfiguration object</param>
    ///<returns>A RequestReponse (string[]) object containing the result</returns>
    public DataRequestResponse<string[]> GetOpenFileNames(FileOpenConfiguration config)
    {
        return FormManager.GetOpenFileNames(config);
    }

    ///<summary>
    /// Displays a File Save dialog
    ///</summary>
    ///<param name="config">A FileSaveConfiguration object</param>
    ///<returns>A RequestReponse (string) object containing the result</returns>
    public DataRequestResponse<string> GetSaveFileName(FileSaveConfiguration config)
    {
        return FormManager.GetSaveFileName(config);
    }

    private void InitialiseLocal()
    { 
        InitialiseEvents();
    }

    protected virtual void InitialiseEvents()
    {
         CompleteRequested = new EventKey<CancelEventArgs>(Events);
         GenericChangeNotified = new EventKey(Events);
         ShowHelpRequested = new EventKey(Events);
    }

    ///<summary>
    /// Sets the text in the dialog title bar
    ///</summary>
    ///<param name="caption">A string representing the caption text to display</param>
    public void SetCaption(string caption)
    {
        if (IsDisposed)
        {
            return;
        }

        if (InvokeRequired)
        {
            MethodInvoker del = () => SetCaption(caption);
            Invoke(del);
            return;
        }

        Text = caption;
    }

    #endregion

}

ControllableViewBase:

public partial class ControllableViewBase : MvpViewBase, IControllableView
{

    #region Event Keys

    public EventKey CloseRequested { get; private set; }
    public EventKey InitialiseCompleteNotified { get; private set; }
    public EventKey OkRequested { get; private set; }
    public EventKey RevertRequested { get; private set; }
    public EventKey SaveRequested { get; private set; }

    #endregion

    #region Properties

    public bool CloseOptionEnabled
    {
        get { return closeButton.Enabled; }
        set { closeButton.Enabled = value; }
    }

    public bool HelpOptionEnabled
    {
        get { return helpButton.Enabled; }
        set { helpButton.Enabled = value; }
    }

    public bool OkOptionEnabled
    {
        get { return okButton.Enabled; }
        set { okButton.Enabled = value; }
    }

    public bool RevertOptionEnabled
    {
        get { return revertButton.Enabled; }
        set { revertButton.Enabled = value; }
    }

    public bool SaveOptionEnabled
    {
        get { return saveButton.Enabled; }
        set { saveButton.Enabled = value; }
    }

    #endregion

    #region Constructors

    ///<summary>
    /// The Form Constructor
    ///</summary>
    public ControllableViewBase()
    {
        InitializeComponent();

        if (AppCommon.RunningFromVisualStudioDesigner)
        {
            return;
        }

        Initialise();
    }

    #endregion

    #region Methods

    private void ControllableViewLoad()
    {
        SetButtonLocations();
    }

    private void HookEvents()
    {
        Load += (sender, args) => ControllableViewLoad();
        closeButton.Click += (sender, e) => CloseRequested.Raise(this);
        helpButton.Click += (sender, e) => ShowHelpRequested.Raise(this);
        okButton.Click += (sender, e) => OkRequested.Raise(this);
        revertButton.Click += (sender, e) => RevertRequested.Raise(this);
        saveButton.Click += (sender, e) => SaveRequested.Raise(this);
    }

    protected void Initialise()
    {
        InitialiseLocalEvents();
        HookEvents();
    }

    private void InitialiseLocalEvents()
    {
        CloseRequested = new EventKey(Events);
        InitialiseCompleteNotified = new EventKey(Events);
        OkRequested = new EventKey(Events);
        RevertRequested = new EventKey(Events);
        SaveRequested = new EventKey(Events);
    }


    protected virtual void SetButtonLocations()
    {
        int buttonCount = footerPanel.Controls.OfType<Button>().Count();
        const int buttonWidth = 75;
        const int gap = 6;

        int totalWidth = buttonCount * buttonWidth + (gap * buttonCount - 1);
        int left = footerPanel.Width - totalWidth - 6;

        okButton.Left = left;
        left += buttonWidth + gap;
        saveButton.Left = left;
        left += buttonWidth + gap;
        closeButton.Left = left;
        left += buttonWidth + gap;
        revertButton.Left = left;
        left += buttonWidth + gap;
        helpButton.Left = left;
    }

    #endregion

}

The interfaces define the events and methods in the code, but I can post them if required...

Thanks for looking and for any help offered.

Edit 2

Here is the call stack from the error, in case it helps give anyone any clues:

Instances of this error (1)

at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)
at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
at Microsoft.VisualStudio.Design.VSTypeResolutionService.AssemblyEntry.Search(String fullName, String typeName, Boolean ignoreTypeCase, Boolean allowPrivate, Assembly& assembly, String description)
at Microsoft.VisualStudio.Design.VSTypeResolutionService.AssemblyEntry.Search(String fullName, String typeName, Boolean ignoreTypeCase, Assembly& assembly, String description)
at Microsoft.VisualStudio.Design.VSTypeResolutionService.SearchProjectEntries(AssemblyName assemblyName, String typeName, Boolean ignoreTypeCase, Assembly& assembly)
at Microsoft.VisualStudio.Design.VSTypeResolutionService.SearchEntries(AssemblyName assemblyName, String typeName, Boolean ignoreCase, Assembly& assembly, ReferenceType refType)
at Microsoft.VisualStudio.Design.VSTypeResolutionService.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, ReferenceType refType)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name)
at System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IDesignerHost.GetType(String typeName)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.EnsureDocument(IDesignerSerializationManager manager)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)  
oldcoder
  • 342
  • 2
  • 12
  • 2
    You will have to show us some code. In particular the code for MpvViewBase and one example that inherits from it. *I am particularly interested in whether either of them is a generic class.* – mjwills Jun 17 '17 at 09:43
  • The designer only handles simplest form inheritance where default parameterless contructor is required and with other criteria. You cannot do whatever you want. – Lex Li Jun 17 '17 at 11:29
  • 2
    1.0.6377.15105 is a pretty horrid version number. And yes, very easily fatal when the build system changes it, instantly making the base class invalid. Locate the AssemblyInfo.cs file for the assembly and change the [AssemblyVersion] attribute from "1.0.*" to something more reasonable, like "1.1.0.0". Google "semantic versioning" for a decent strategy. – Hans Passant Jun 17 '17 at 13:15
  • @HansPassant: That is just my point - it is NOT my version number. As stated in the question a) that version number does not exist and b) there should be no dll or version since we are opening the source in the project that generates the dll... There is no version number in AssemblyInfo.cs, since it is contained in a linked file from the main project which automatically assigns the version number of each build. The current version number (or rather the prior one since I only increment when I build for release) is 1.0.0.566. – oldcoder Jun 17 '17 at 13:26
  • @mjwills: I will add the code, but it ain't gonna help since these are trivial classes. None are generic. – oldcoder Jun 17 '17 at 13:27
  • 2
    It is an *auto-generated* version number, produced by `"1.0.*"`. You can search for that. – Hans Passant Jun 17 '17 at 13:31
  • @HansPassant: I am really grateful for your efforts to assist, but I don't know how to make it any clearer. There are *NO* automatic version numbers in the entire solution... which of course why I am so confused that Visual Studio is coming up with a totally irrelevant version number. – oldcoder Jun 17 '17 at 13:40
  • Do these help? https://stackoverflow.com/questions/11406298/method-x-from-type-y-in-assembly-z-does-not-have-an-implementation https://stackoverflow.com/questions/948785/typeloadexception-says-no-implementation-but-it-is-implemented Are you referencing CommonForms as a binary reference or a project reference? – mjwills Jun 17 '17 at 13:42
  • @HansPassant: Hands up, I was absolutely wrong! I thought that there were no automatic version numbers in the entire solution... which of course why I was so confused that Visual Studio was coming up with a totally irrelevant version number. However, I checked as you suggested and there was an auto on the AssemblyVersion in the VersionInfo.cs file linked to all 123 projects in the solution. I changed it to mirror the Assembly File Version. This has made no difference except that the correct version number is now displayed. – oldcoder Jun 17 '17 at 13:48
  • @mjwills: CommonForms is not a reference AT ALL. Both forms are PART OF CommonForms... No reference is therefore needed as far as I am aware. Both are in the same CommonForms namespace. – oldcoder Jun 17 '17 at 13:49
  • Is `AppCommon` a separate project? If so, does that separate project reference the CommonForms project? – mjwills Jun 17 '17 at 14:02
  • Does the issue go away if ControllableViewBase's constructor calls MvpViewBase's constructor? If you add `return;` after each of their `InitializeComponent();` calls? – mjwills Jun 17 '17 at 14:04
  • The first one was a problem with an older DLL in the GAC. Since there is no DLL (we are in the source of the CommonForms dll at the time) and the application is never installed I cannot see how there can be one there... but in view of my mistake on version numbers when responding to @HansPassant's comment I will double and triple check now! – oldcoder Jun 17 '17 at 14:06
  • @mjWills: the AppCommon call is there only to force InitialiseLocal not to fire when opening in the designer. It is a simple a static class containing relevant values that are re-usable throughout the application. It does not reference CommonForms, as that would be a circular reference and therefore illegal. It makes no difference whether or not the call is there - I also tried removing all code other than InitializeComponent and the result was still the same. – oldcoder Jun 17 '17 at 14:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/146945/discussion-between-oldcoder-and-mjwills). – oldcoder Jun 17 '17 at 14:10
  • 1
    Designer is a complicated but also a stupid beast. To display your form, it actually **creates** the **base** class object. After that, it buildsup a, let's say, maquette or prototype of the view according to a deserialized (sic!) code of IniializeComponent from Designer.cs file. No problem if the base is Window or UserControl etc from the framework - its code will be simply loaded from the framework. However, if the base is Your class, then it can't "just load" the base class code. It silently compiles it (/obj folder probably), and loads it so it can use it for displaying things for you. – quetzalcoatl Jun 17 '17 at 19:20
  • There are few important points here: (1) the base class object is really created, initialized, builtup and used as-is. It's constructor will be called in full, properties will be set, all the code will just run. That's why i.e. base class cannot be abstract. (2) base class has to compile on its own (3) if the base class is heavy or poorly written, and/or your VS version has unfixed bugs, then when base class changes, VS has to recompile and reload the base class code. It can actually fail on that, and **can accidentally use old code** even though you see fresh base class code in the editor. – quetzalcoatl Jun 17 '17 at 19:24
  • All of that is just the tip of the iceberg. There's a lot more things that can go wrong. I battled with similar issues for a long time before moving to newer frameworks like WPF, and I can only tell you - except some common things (abstract base class, generic base class, heavy constructors in base classes, property setters connecting to the database, ...) each case was different and tough to diagnose. I usually purged **everything**: kill VS, delete whole /bin, /obj, /temp, windows/temp, appdata/local/temp, etc, then start VS and check if errors changed. If not, try another (virtual) machine. – quetzalcoatl Jun 17 '17 at 19:33
  • and finally, and maybe most importantly, try using the same VS version as back then long time ago when the code was written. VS changes, Designer changes in some subtle ways, and actually adding a servicepack or upgrading the VS can break it sometimes for you.. so, my question is: did you try all of that? huge purge, or getting a clean machine and using an old version of VS? if not, and if possible, please do try. – quetzalcoatl Jun 17 '17 at 19:36
  • If you create a new, 'cut-down' project from scratch (one you could upload somewhere so that we could have a look at it) does it still occur? – mjwills Jun 18 '17 at 09:23
  • @quetzalcoatl: I have tried most of what you describe, and I too suspect a Microsoft silent update as the culprit - not least because it all worked fine until a few days ago. There is almost nothing in these clases, as you can see from the posted code, and I have deliberately added a call to skip construction of any complex objects if the construction call is made in the designer. I am not sure where I would get such an old version of VS and anyway it would probably update itself again :-) I will look to see if there is anything else in your list that I can do, thanks for the input. – oldcoder Jun 18 '17 at 13:54
  • 1
    @mjwills: Yes, we did that (or at least as clean as we could as this is a major applications with millions of lines of code and 123 projects just in the main application never mind the libraries and test solutions). I will look to see if we can do an absolutely clean solution and add in only the code for those forms and their ancestors to see what happens. This will not be a trivial job, though... I will report back. – oldcoder Jun 18 '17 at 13:57
  • Awesome, thanks @oldcoder . – mjwills Jun 18 '17 at 13:58
  • @mjwills: I generated a whole new project. I copied the compulsory forms in from of the main application, but It still had the same error. Next, I stripped everything right back, commenting out anything in the new project that was not part of the framework. Bingo, I could get the form to display. I then put it all back bit by bit... and when it was all back it still worked!! There is no rhyme nor reason to this, but my next step is to remove the existing source from the main application, put back the ones from the test solution. Will let you know if it still works once that is done... – oldcoder Jun 18 '17 at 18:16
  • @mjwills: I put literally the same code back into the original solution - physically copied the files overwriting the originals. Cleaned and rebuilt the solution, and tested. Nothing... just as broken as before we started. I guess that suggests a problem perhaps in the project file given that there are hundreds of forms fewer in that project. I plan to transfer that file too and see what happens then. I will keep you posted. – oldcoder Jun 18 '17 at 18:36
  • 1
    @mjwills: That was the problem. I put the project file from the test solution in, rebuilt, made a few additions when it would not build, and now I have the designer again. I just have to add back each form one at a time (hundreds of them) checking to make sure it still loads after each one... I will be here ages, but hopefully at the end of it I will either have found out what was causing it or have a working designer. Thanks for sticking with me on this one, your support has been invaluable. I will report back when I get to the end! – oldcoder Jun 18 '17 at 18:52
  • @quetzalcoatl: It would seem not. The problem has proven to be in the Project file, although I have not been able to determine which part of the file was the problem as it was huge. I described how I proved this in previous comments, and it continues to appear proven. I am currently working my way through the 1169 issues that remain, basically adding one form and reference at a time and checking that it is still working as expected and that the designer still loads. I am over half way through the job, and so far it has not broken... – oldcoder Jun 18 '17 at 21:17
  • Absolutely strange. I know the structure/function of .csproj files quite well, and I see nothing that could impact it, especially - limtied to just the designer.. rather, it would impact compilation. I'm really curious what you will end up with. I have mixed feelings, should I wish you finding something extraordinary and logical, or just getting it quickly magically work fine after all :) btw. 1169 sounds large, maybe try bisecting :) – quetzalcoatl Jun 18 '17 at 21:26
  • 1
    @quetzalcoatl: I agree fully. I am unable to confirm *why* this has worked, but it most definitely has. After five days of struggle I have gone through adding back everything I had ripped out, checking all the way through. It was a bit of a struggle at times, for example the access modifier on the Resources for the project had changed to which caused a problem or two :-) I now have a fully working solution, but it is definitely a 'magical' result with no logical cause that I can think of. However, it didn't work at all until I copied over the project file from the test solution... – oldcoder Jun 20 '17 at 13:08

1 Answers1

0

I am posting this answer for completeness and just in case it helps anyone else, in that it worked for me but I have no idea why...

I created a test solution and put the offending files into it alone, and I commented out all code that did not emanate from the framework. At that point I was able to fire up the designer.

Next I uncommented all the code one bit at a time, and it still worked. I copied the files back to the original Solution, but there it still did NOT work.

Next stage was to copy over the project file from the test solution, at which point it DID work, but of course all the other files from the project were no longer part of the project. In order to try to find the cause, I added back the files one at a time, each time checking that the designer still worked after the file had been added.

There were a few minor knock-on effects that I had to deal with, but basically I now have a fully working solution with forms that open in the designer as they always used to.

Whether this is purely coincidental (MS could perhaps have done a background software fix in the meantime for example) or whether it was actually the project file at fault I am unable to say. However, if someone else has a similar problem to mine and as in my case none of the other solutions on StackOverflow and Google have worked, it may be worth following the same pattern to see if it helps...

oldcoder
  • 342
  • 2
  • 12