То, что я хочу сделать, записать некоторые классы в C# в новом пространстве имен, которые действуют как классы обертки для классов в другом пространстве имен. Иногда класс обертки не нужен, но я все еще хочу соответствующий класс в новом пространстве имен. И я хочу точную копию класса. Существует ли способ определить класс в новом пространстве имен путем обращения к определению другого класса? Другими словами, я хочу псевдоним.
Разъясниться, что я имею в виду, если существующее пространство имен называют "Namespace1" и новым пространством имен, называют "Namespace2", с помощью кода как это в Namespace2:
using Class1 = Namespace1.Class1;
не работал бы потому что Namespace2.Class1
не существовал бы. Class1 был бы только искажен "частный" к Namespace2 и не "общедоступный" к Namespace2. Если я мог бы использовать Namepsace2.Class1
снаружи пространства имен, и если это все еще относилось бы к Namespace1.Class1
, затем это было бы тем, что я хочу.
Я полагал, что мог бы быть способ выполнить это с атрибутами или отражением, возможно. Если были некоторые директивы препроцессору или макросы, которые могли бы скопировать код, который будет работать также, но очевидно C# не имеет ничего как этот.
Похоже, вам нужно отобразить определение одного класса в другое.
Это можно сделать вручную (через множество кодов котельной) или автоматически через инструмент, подобный Automatper .
Вы можете использовать с использованием Создать псевдоним к типу :
using Project = PC.MyCompany.Project;
Да, вы можете сделать это, если я правильно понимаю здесь MSDN MSDN Attright a MSDN MSDN на Alias Nameswance Pasting
вот волшебство
using colAlias = System.Collections
, поэтому я сглаживающую систему. пространство имен.
Вот пример
using colAlias = System.Collections;
namespace System
{
class TestClass
{
static void Main()
{
// Searching the alias:
colAlias::Hashtable test = new colAlias::Hashtable();
// Add items to the table.
test.Add("A", "1");
test.Add("B", "2");
test.Add("C", "3");
foreach (string name in test.Keys)
{
// Seaching the gloabal namespace:
global::System.Console.WriteLine(name + " " + test[name]);
}
}
}
}
Если вы определяете класс в другом пространстве имен, это будет другой класс. MyNewnameSpace.myclass
и myoldnamepace.myclass
- два различных типа .NET.
Вы можете легко инкапсулировать все публичные API вашего первого класса в новом классе, но это потребует некоторый код котельной. AOP может обеспечить способ сделать это просто, используя что-то вроде postsharp (с пользовательским фильтром).
Проблема заключается в том, что библиотека выражений создает исключение, если заданы два аргумента несовпадающей возможности использования значения null. Вот простое репро:
Expression<Func<DateTime?>> ex1 = ()=>DateTime.Now;
Expression<Func<DateTime>> ex2 = ()=>DateTime.Now;
var ex3 = Expression.GreaterThan(ex1.Body, ex2.Body);
Мне непонятно, жучок это или нет; правила C # требуют, чтобы в этом сценарии операнд, не допускающий значения NULL, был преобразован в операнд, допускающий значение NULL, и использовалась форма сравнения, не допускающая значения NULL. Однако , библиотека дерева выражений не обязана следовать правилам C # , потому что, конечно, библиотека дерева выражений может использоваться для представления выражений C #, выражений Python, выражений JScript, выражений VB и так далее; он не может следовать всем правилам любого возможного языка.
Но, независимо от этого, это может быть ошибкой, поэтому я передам ее команде дерева выражений и посмотрю, что они скажут. В то же время, вы можете легко работать с ним, определяя свой собственный метод помощника, который исправляет операнды вверх. Быстрый эскиз будет:
static Expression MyGreaterThan(Expression e1, Expression e2)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.GreaterThan(e1, e2);
}
static bool IsNullableType(Type t)
{
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
}
Однако, обратите внимание, что это не проверяет, что типы e1 и e2 отличаются только нулевыми значениями; если передать значение int, допускающее значение null, и двойное выражение, не допускающее значения null, случаются плохие вещи. Я оставляю это как упражнение, чтобы реализовать лучшую логику, которая проверяет, имеют ли два выражения тип, который отличается только нулевая способность.
-121--1380350-Было бы здорово, если бы был какой-то волшебный атрибут, который я мог бы просто добавить к свойству в «автоэкспрессию» свойство и сделать LinqToSql счастливым, вместо того, чтобы обернуть его в Выражение <... >
Есть, очень почти. Вы все еще должны сделать некоторые работы, но Дэмиен Guard и друзья сделали трудное для вас: Клиентские свойства и любой удаленный LINQ провайдер
Круто, что он работает с любым LINQ провайдер, который поддерживает выражения вы используете.
Обновление: Проблема, связанная со второй версией (с интерфейсом), заключается в том, что провайдеру Queryable необходимо выяснить, что такое реализация интерфейса, потому что он должен транслитировать его в имя таблицы. Но весь пункт интерфейса заключается в том, что пользователь интерфейса должен быть агностичным в отношении типа реализации, так что провайдер будет работать в общих целях с интерфейсом. Так что не думаю, что вторая форма сработает.
-121--1862543-Классы обертки WRT, я много раз обнаруживаю, что люди переносят классы только для расширения функциональности, а не для выражения отношения is-a. В этих случаях можно рассмотреть Методы расширения .
Это позволяет писать методы для существующих классов, а не выводить только для добавления дополнительных функциональных возможностей. Для типа
/// <summary>
/// ICollectionExtensions
/// </summary>
internal static class ICollectionExtensions
{
public static void AddNew<T>(this ICollection<T> self, T data)
{
if (self != null && !self.Contains(data))
{
self.Add(data);
}
}
}
можно использовать .AddNew ()
для типов ICollection < T >
.
Не уверены, что вы пытаетесь сделать, но посмотрите на Automatper .