A natív kód nem fér hozzá a Windows Forms-objektumokhoz

A .NET 5-től kezdve már nem férhet hozzá a Windows Forms-objektumokhoz natív kódból.

Módosítás leírása

A korábbi .NET-verziókban egyes Windows Forms-típusok a COM-interop számára láthatóként lettek díszítve, így a natív kódhoz is elérhetők voltak. A .NET 5-től kezdve egyetlen Windows Forms API sem látható a COM interop vagy a natív kód számára. A .NET-futtatókörnyezet már nem támogatja az egyéni típusú kódtárak létrehozását a dobozon kívül. Emellett a .NET-futtatókörnyezet nem függhet a .NET-keretrendszer típustárától (amihez az osztályok alakjának fenntartása szükséges a .NET-keretrendszerben).

A változás oka

  • ComVisible(true) A típustár (TLB-fájl) generálásához és kereséséhez használt enumerációk eltávolítása: Mivel a .NET Core nem biztosít WinForms TLB-t, nincs érték az attribútum megtartásában.
  • A ComVisible(true) eltávolítása a AccessibleObject osztályokból: Az osztályok nem rendelkeznek létrehozható paraméter nélküli konstruktorral, és egy már meglévő példány COM-hoz való hozzáférhetővé tétele nem igényli ezt az attribútumot.
  • ComVisible(true) eltávolítása a Control és Component osztályokból: Ez lehetővé tette a WinForms-vezérlők OLE/ActiveX-en keresztüli befogadását, például VB6-ban vagy MFC-ben. Ehhez azonban szükség van egy TLB-re a WinForms-hez, amely már nem áll rendelkezésre, valamint a beállításjegyzék-alapú aktiválásra, amely szintén nem működne az alapértelmezett beállításokkal. A WinForms-vezérlők COM-alapú üzemeltetése általában nem volt karbantartva, ezért a támogatás nem támogatott állapotban maradt.
  • ClassInterface Attribútumok eltávolítása a vezérlőkből: Ha az OLE/ActiveX használatával történő üzemeltetés nem támogatott, ezekre az attribútumokra már nincs szükség. Ezeket más helyeken tartják, ahol az objektumok továbbra is ki vannak téve a COM-nak, és az attribútum releváns lehet.
  • Eltávolítása ComVisible(true) elemeknek EventArgs: Valószínűleg OLE/ActiveX-üzemeltetéssel használták őket, ami már nem támogatott. Ezek sem coCreateable, így az attribútumnak nincs célja. Emellett a meglévő példányok TLB megadása nélkül való felfedésének nincs értelme.
  • A ComVisible(true) eltávolítása a delegáltakról: A cél ismeretlen, de mivel a WinForms Controls ActiveX-üzemeltetése már nem támogatott, valószínűtlen, hogy bármilyen haszna lenne.
  • ComVisible(true) Néhány nem nyilvános kód eltávolítása: Az egyetlen potenciális felhasználó az új Visual Studio Designer lehetne, de egy GUID megadása nélkül nem valószínű, hogy még szükséges.
  • ComVisible(true) Néhány tetszőleges nyilvános tervezői osztály eltávolítása: Előfordulhat, hogy a régi Visual Studio-tervező COM-interop használatával beszélt ezekkel az osztályokkal. A régi tervező azonban nem támogatja a .NET Core-t, ezért kevés embernek lenne szüksége ezekre.ComVisible
  • IWin32Window meghatározta ugyanazt a GUID-t, amelyet a .NET-keretrendszerben definiáltak, ami veszélyes következményekkel jár. Ha a .NET-keretrendszerrel való együttműködésre van szüksége, használja a ComImport.
  • A WinForms IDataObject felügyelt keretrendszer készült el ComVisible. Ez nem kötelező, mert a ComImport felületi deklaráció külön van a IDataObject COM-interophoz. Ez ellentétes a felügyelt IDataObject beállítással ComVisible, mivel nincs TLB megadva, és a rendezés mindig sikertelen lesz. Emellett a GUID nincs megadva, és eltér a .NET-keretrendszertől, így a nem dokumentált IID eltávolítása valószínűleg negatív hatással lesz az ügyfelekre.
  • Eltávolítása ComVisible(false): Ezek látszólag tetszőleges helyekre vannak helyezve, és redundánsak, ha az alapértelmezett nem teszi ki az osztályokat a COM-interoperabilitáshoz.

Bevezetett verzió

.NET 5.0

Az alábbi példa a .NET-keretrendszeren és a .NET Core 3.1-en működik. Ez a példa a .NET-keretrendszer típusú kódtárra támaszkodik, amely lehetővé teszi, hogy a JavaScript visszahívja az űrlap alosztályát tükröződés útján.

[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class Form1 : Form
{
    private WebBrowser webBrowser1 = new WebBrowser();

    protected override void OnLoad(EventArgs e)
    {
        webBrowser1.AllowWebBrowserDrop = false;
        webBrowser1.IsWebBrowserContextMenuEnabled = false;
        webBrowser1.WebBrowserShortcutsEnabled = false;
        webBrowser1.ObjectForScripting = this;

        webBrowser1.DocumentText =
            "<html><body><button " +
            "onclick=\"window.external.Test('called from script code')\">" +
            "call client code from script code</button>" +
            "</body></html>";
    }

    public void Test(String message)
    {
        MessageBox.Show(message, "client code");
    }
}

A példa kétféleképpen használható a .NET 5-ös és újabb verzióiban:

  • Vezessen be egy felhasználó által deklarált ObjectForScripting objektumot, amely támogatja IDispatch (amely alapértelmezés szerint van alkalmazva, kivéve, ha kifejezetten a projekt szintjén módosul).

    public class MyScriptObject
    {
        private Form1 _form;
    
        public MyScriptObject(Form1 form)
        {
            _form = form;
        }
    
        public void Test(string message)
        {
            MessageBox.Show(message, "client code");
        }
    }
    
    public partial class Form1 : Form
    {
        protected override void OnLoad(EventArgs e)
        {
            ...
    
            // Works correctly.
            webBrowser1.ObjectForScripting = new MyScriptObject(this);
    
            ...
        }
    }
    
  • Deklaráljon egy felületet a közzéteendő metódusokkal.

    public interface IForm1
    {
        void Test(string message);
    }
    
    [ComDefaultInterface(typeof(IForm1))]
    public partial class Form1 : Form, IForm1
    {
        protected override void OnLoad(EventArgs e)
        {
            ...
    
            // Works correctly.
            webBrowser1.ObjectForScripting = this;
    
            ...
        }
    }
    

Érintett API-k

Minden Windows Forms API.