Aracılığıyla paylaş


Yerel kod Windows Forms nesnelerine erişemiyor

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

Açıklamayı değiştir

Ö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 Control sınıflarından Component 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.
  • ComVisible(true)'den EventArgs'in kaldırılması: 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.
  • Temsilcilerden ComVisible(true) kaldırılması: Amacı bilinmiyor, ancak artık ActiveX'in WinForms Kontrollerini barındırması desteklenmediğinden dolayı yararlı olması olası görünmüyor.
  • 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.
  • Bazı gelişi güzel genel tasarımcı sınıflarından ComVisible(true)'nun kaldırılması: Eski Visual Studio tasarımcısı bu sınıflarla konuşmak için COM birlikte çalışmayı kullanmış olabilir. Ancak, eski tasarımcı .NET Core'u desteklemediği için bunlara ComVisible ihtiyacı olan çok az kişi 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.
  • WinForms IDataObject yönetilen olarak ComVisible yapıldı. Bu gerekli değildir, ComImport COM birlikte çalışabilirlik için IDataObject ayrı bir arabirim bildirimi vardır. TLB sağlanmadığından ve aktarma her zaman başarısız olacağından, yönetilen IDataObject öğesinin ComVisible olması verimsizdir. 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.
  • ComVisible(false) öğesinin kaldırılması: Bunlar rastgele gibi görünen yerlere yerleştirilir ve varsayılan olarak sınıfları COM birlikte çalışabilirlik 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:

  • Kullanıcı tarafından bildirilen ObjectForScripting nesnesini tanıtın, bu nesne IDispatch destekler (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.