Genişletme yöntemleri, genel olmayan bir statik sınıfta tanımlanmalıdır


213

Hatayı alıyorum:

Genişletme yöntemleri, genel olmayan bir statik sınıfta tanımlanmalıdır

Çizgide:

public class LinqHelper

İşte Mark Gavells koduna dayanan yardımcı sınıf. Cuma günü bıraktığımda iyi çalıştığından eminim bu hatanın ne anlama geldiği konusunda gerçekten kafam karıştı!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Linq.Expressions;
using System.Reflection;

/// <summary>
/// Helper methods for link
/// </summary>
public class LinqHelper
{
    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "OrderBy");
    }
    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "OrderByDescending");
    }
    public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "ThenBy");
    }
    public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "ThenByDescending");
    }
    static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName)
    {
        string[] props = property.Split('.');
        Type type = typeof(T);
        ParameterExpression arg = Expression.Parameter(type, "x");
        Expression expr = arg;
        foreach (string prop in props)
        {
            // use reflection (not ComponentModel) to mirror LINQ
            PropertyInfo pi = type.GetProperty(prop);
            expr = Expression.Property(expr, pi);
            type = pi.PropertyType;
        }
        Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
        LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

        object result = typeof(Queryable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), type)
                .Invoke(null, new object[] { source, lambda });
        return (IOrderedQueryable<T>)result;
    }
}

Yanıtlar:


309

değişiklik

public class LinqHelper

için

public static class LinqHelper

Bir uzantı yöntemi oluştururken aşağıdaki noktalara dikkat edilmelidir:

  1. Bir uzantı yöntemini tanımlayan sınıf non-generic,static venon-nested
  2. Her genişletme yöntemi bir staticyöntem olmalıdır
  3. Extension yönteminin ilk parametresi thisanahtar sözcüğü kullanmalıdır .

Sınıfı App_Code içine yerleştirdiyseniz, sınıf tanımında statik anahtar kelimeye sahip olmak gerekir, ancak başka bir klasöre yerleştirirseniz normal sınıf olarak kullanmak iyi olur.
DT

1
Bir durumda, public static class IQueryable<T> where T : MyBaseClassbu hatayı da üreten kullanmıştım . where T : MyBaseClassİfade vermeden bireysel yöntemler üzerinde aittir <T>statik sınıfına.
Bron Davies

1
Peki ya sınıf Kısmi ise? Bu çözüm benim için işe yaramadı.
fandango68

1
Teşekkürler dostum, "bu" parametreye yakalandım!
Roberto Gata

1
Sınıfınızı yanlışlıkla bir uzantı yöntemine dönüştürdüyseniz (derleyiciye göre) bu derleyiciyi alabileceğinizi unutmayın. Bkz bu cevabı statik yöntemlere ilişkin olarak ve bu cevabı açısından thisyöntem argümanlar.
Maarten Bodewes

26

statik işlevlere sahip olmak istemiyorsanız sadece bağımsız değişkenlerdeki "this" anahtar sözcüğünden kurtulun.


6
Visual Studio'nun neden derslerimden birini genişletme yöntemi yapmaya çalıştığımı düşündüğünü anlamaya çalışmak için başımı kaşıyordum. Anlaşılan thisyöntem imzalarımın içine gömülmüş bir anahtar kelimem var. Kaldırıldığında hata giderildi.
Fütemire

20

staticSınıf bildirimine anahtar kelime ekleyin :

// this is a non-generic static class
public static class LinqHelper
{
}

16

Değiştirmeyi deneyin

public class LinqHelper

için

 public static class LinqHelper

15

Olarak değiştir

public static class LinqHelper

15

Nathan gibi bir hata yaşayan insanlar için bir çözüm:

Anında derleyici bu Uzantı Yöntemi hatası ile ilgili bir sorun var gibi görünüyor ... ekleme staticde bana yardımcı olmadı.

Hatanın nedenini bilmek ister misiniz?

Ancak geçici çözüm , aynı dosyada bile yeni bir Extension sınıfı (iç içe değil) yazmak ve yeniden oluşturmaktır.

Bu iş parçacığının bulduğum (sınırlı) çözümü geçmeye değer yeterli görüş elde ettiğini düşündüm. Çoğu kişi bir çözüm için google-ing'den önce muhtemelen 'statik' eklemeyi denedi! ve bu geçici çözümü başka hiçbir yerde görmedim.


Aynı sorunu yaşadım. Sınıfta statik bir işlev eklediğimi fark ettim ve yorum yapmayı unuttum. Bu benim sınıfımı statik hale getirdi ve bu nedenle bu hatayı veriyordu. Sınıfınızda statik nesneler olup olmadığını kontrol edin.
Mahesh

1

Genişletme yöntemi statik bir sınıf içinde olmalıdır. Bu yüzden lütfen uzatma yönteminizi statik bir sınıfa ekleyin.

yani örneğin böyle olmalı

public static class myclass
    {
        public static Byte[] ToByteArray(this Stream stream)
        {
            Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length);
            Byte[] buffer = new Byte[length];
            stream.Read(buffer, 0, length);
            return buffer;
        }

    }

Bu yıllar önce verilen cevaplardan nasıl farklı?
Maarten Bodewes

1

Statik sınıfa ve geri değiştirmeyi deneyin. Görsel stüdyo yanlış bir pozitif olduğunda şikayetçi olabilir.


0

Benzer bir sorunla karşılaştım, bir 'foo' klasörü oluşturdum ve foo içinde bir "sınıf" oluşturdum, sonra yukarıda belirtilen hatayı alıyorum. Bir düzeltme, "public static class LinqHelper" olacak sınıfa daha önce bahsedildiği gibi "static" eklemektir.

Benim varsayım, foo klasörünün içinde bir sınıf oluşturduğunuzda onu bir uzantı sınıfı olarak kabul ettiğidir, bu nedenle diğer şeylerin yanı sıra aşağıdaki kural geçerlidir:

1) Her genişletme yöntemi statik bir yöntem olmalıdır

Statik istemiyorsanız. Geçici çözümüm, doğrudan ad alanının altında bir sınıf oluşturmak ve "foo" klasörüne sürüklemekti.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.