Yerel kod Windows Forms nesnelerine erişemiyor

.NET 5'ten başlayarak, windows forms nesnelerine artık yerel koddan erişemezsiniz.

Açıklama değiştirildi

Önceki .NET sürümlerinde, bazı Windows Forms türleri COM birlikte çalışma için görünür olarak düzenlenmiş ve bu nedenle yerel kod tarafından erişilebilirdi. .NET 5'den başlayarak, COM birlikte çalışmasında hiçbir Windows Forms API'sine görünür veya yerel kod tarafından erişilemez. .NET çalışma zamanı artık kutudan özel tür kitaplıkları oluşturmayı desteklemez. Buna ek olarak, .NET çalışma zamanı .NET Framework için tür kitaplığına bağımlı olamaz (bu, .NET Framework'te olduğu gibi sınıfların şeklinin korunmasını gerektirir).

Değişiklik nedeni

  • ComVisible(true) Tür kitaplığı (TLB dosyası) oluşturma ve arama için kullanılan numaralandırmalardan kaldırma: .NET Core tarafından sağlanan WinForms TLB olmadığından, bu özniteliği tutmanın bir değeri yoktur.
  • ComVisible(true) Sınıflardan AccessibleObject kaldırma: Sınıflar CoCreateable değildir (parametresiz oluşturucuları yoktur) ve zaten var olan bir örneği COM'a açmak bu özniteliği gerektirmez.
  • ComVisible(true) ve Component sınıflarından Control kaldırılması: Bu, WINForms denetimlerinin OLE/ActiveX aracılığıyla, örneğin VB6 veya MFC'de barındırılmasına izin vermek için kullanılır. Ancak bu, WinForms için artık sağlanmayan bir TLB'nin yanı sıra kayıt defteri tabanlı etkinleştirmeyi de gerektirir ve bu da kutudan çıkmaz. Genel olarak, WinForms denetimlerinin COM tabanlı barındırılması için bakım yapılmadığından destek desteklenmeyen bir durumda bırakmak yerine kaldırıldı.
  • Denetimlerden özniteliklerin ClassInterface kaldırılması: OLE/ActiveX aracılığıyla barındırma desteklenmiyorsa, bu özniteliklere artık gerek yoktur. Bunlar, nesnelerin hala COM'a açık olduğu ve özniteliğin ilgili olabileceği başka yerlerde tutulur.
  • öğesinin ComVisible(true) kaldırılması EventArgs: Bunlar büyük olasılıkla artık desteklenmeyen OLE/ActiveX barındırma ile kullanılmıştır. Bunlar da CoCreateable olmadığından özniteliğin bir amacı yoktur. Ayrıca, TLB sağlamadan mevcut örneklerin açığalanması mantıklı değildir.
  • ComVisible(true) Temsilcilerden kaldırma: Amaç bilinmiyor, ancak WinForms Denetimlerinin ActiveX barındırması artık desteklenmediğinden, herhangi bir yararlılığı olma olasılığı düşüktür.
  • ComVisible(true) Genel olmayan bazı kodlardan kaldırılması: Tek olası tüketici yeni Visual Studio tasarımcısı olabilir, ancak GUID belirtilmediğinde hala gerekli olma olasılığı düşüktür.
  • ComVisible(true) Bazı rastgele genel tasarımcı sınıflarından kaldırılması: Eski Visual Studio tasarımcısı bu sınıflarla konuşmak için COM birlikte çalışma kullanıyor olabilir. Ancak, eski tasarımcı .NET Core'un desteklemiyor, bu nedenle birkaç kişinin bunlara ComVisibleihtiyacı olacaktır.
  • IWin32Window tehlikeli sonuçları olan .NET Framework'te tanımlanan GUID'nin aynısını tanımladı. .NET Framework ile birlikte çalışmanız gerekiyorsa kullanın ComImport.
  • Yönetilen IDataObject WinForms yapıldı ComVisible. Bu gerekli değildir, COM birlikte çalışma için IDataObject ayrı ComImport bir arabirim bildirimi vardır. TLB sağlanmadığından ve sıralama her zaman başarısız olacağından, yönetilen IDataObject öğesinin olması ComVisibleters bir işlemdir. Ayrıca GUID belirtilmemiş ve .NET Framework'ten farklı olduğundan, belgelenmemiş bir IID'nin kaldırılmasının müşterileri olumsuz etkileme olasılığı düşüktür.
  • öğesinin ComVisible(false)kaldırılması: Bunlar rastgele gibi görünen yerlere yerleştirilir ve varsayılan olarak sınıfları COM birlikte çalışması için kullanıma sunmamak olduğunda yedeklidir.

Sürüm kullanıma sunulmuştur

.NET 5.0

Aşağıdaki örnek .NET Framework ve .NET Core 3.1 üzerinde çalışır. Bu örnek, JavaScript'in yansıma yoluyla form alt sınıfına geri çağırmasını sağlayan .NET Framework tür kitaplığını kullanır.

[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");
    }
}

Örneğin .NET 5 ve sonraki sürümlerde çalışmasını sağlamanın iki olası yolu vardır:

  • Destekleyen IDispatch kullanıcı tarafından bildirilen ObjectForScripting bir nesne tanıtın (proje düzeyinde açıkça değiştirilmediği sürece varsayılan olarak uygulanır).

    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);
    
            ...
        }
    }
    
  • Kullanıma sunma yöntemleriyle bir arabirim bildirin.

    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;
    
            ...
        }
    }
    

Etkilenen API’ler

Tüm Windows Forms API'leri.