COM+ и массив Decimal
От: Spiceman  
Дата: 26.06.09 12:15
Оценка:
Всем привет.

Сегодня чуть не убился об клавиатуру. Но решение проблемы таки нашел. Теперь хочу понять, что это было?

Есть COM+ приложение. В нем есть интерфейс и класс, его реализующий. Этот же класс является компонентом COM+. В интерфейсе есть метод, принимающий в качестве параметра массив Decimal. Код для наглядности:

    public interface Interface4
    {
        void Test4(decimal[] ddd);
    }

    [ObjectPooling(true, 1, 100),
    EventTrackingEnabledAttribute(true),
    Guid("DD779496-07EC-424f-A26F-690DE436F320"),
    ClassInterface(ClassInterfaceType.AutoDispatch),
    Transaction(TransactionOption.Required)]
    public class Class4 : ServicedComponent, Interface4
    {
        public void Test4(decimal[] ddd)
        {
                // Мега логика.
        }
    }


Теперь пытаемся вызвать этот метод из клиента:

Class4 c4 = new Class4();
decimal[] ddd = new decimal[] { 111M };
c4.Test4(ddd); // System.ArgumentException: Value does not fall within the expected range.


Убился я собственно перебирая варианты, при которых этот код заработает.

Работает он, если:
1. Убрать у класса реализацию интерфейса. Но этот вариант не подходил, так как в реальном классе на промышленной системе есть уже куча клиентов, использующих этот класс через интерфейс.
2. Изменить тип с decimal, на какой-либо другой, например, double. Но это тоже не айс, так как нужен именно decimal.
3. Передавать массив через ref. На этом варианте и остановился. Но вот вопрос почему именно так??? Что за шляпа? Что не так с типом decimal?
Re: COM+ и массив Decimal
От: Spiceman  
Дата: 26.06.09 12:17
Оценка:
Забыл еще один вариант указать:
4. Если передавать не массив, а просто тип decimal, то есть "void Test4(decimal ddd);". Но этот вариант тоже не подходит, так как нужен был именно массив.
Re: COM+ и массив Decimal
От: baranovda Российская Империя  
Дата: 26.06.09 12:30
Оценка:
Здравствуйте, Spiceman, Вы писали:

S>Всем привет.

S>Что за шляпа? Что не так с типом decimal?

Может быть, грабли потому, что Decimal — это структура и не имеет конструктора без параметров?
Re[2]: COM+ и массив Decimal
От: Spiceman  
Дата: 26.06.09 12:38
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Может быть, грабли потому, что Decimal — это структура и не имеет конструктора без параметров?


Тогда почему, если decimal передавать не в массиве, то все работает?
Re[2]: COM+ и массив Decimal
От: Воронков Василий Россия  
Дата: 26.06.09 12:43
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Может быть, грабли потому, что Decimal — это структура и не имеет конструктора без параметров?


Это с чего она не имеет конструктора без параметров? Что по вашему происходит когда:

var d = default(Decimal);

компилятор фокусы показывает?
Re[3]: COM+ и массив Decimal
От: baranovda Российская Империя  
Дата: 26.06.09 12:43
Оценка:
Здравствуйте, Spiceman, Вы писали:

S>Здравствуйте, baranovda, Вы писали:


S>Тогда почему, если decimal передавать не в массиве, то все работает?


А атрибутом MarshalAs играться не пробовали?
Re[3]: COM+ и массив Decimal
От: baranovda Российская Империя  
Дата: 26.06.09 12:45
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>компилятор фокусы показывает?


В MSDN все Overloads только с параметрами
Re[4]: COM+ и массив Decimal
От: Spiceman  
Дата: 26.06.09 12:50
Оценка:
Здравствуйте, baranovda, Вы писали:

B> А атрибутом MarshalAs играться не пробовали?


Еще десять тысяч вариантов, и я бы сломал клавиатуру.
Если подскажете, что конкретно надо было указать в MarshalAs, буду благодарен. И хотелось бы еще объяснение получить, почему именно так.
Re[4]: COM+ и массив Decimal
От: Воронков Василий Россия  
Дата: 26.06.09 12:56
Оценка:
Здравствуйте, baranovda, Вы писали:

B> В MSDN все Overloads только с параметрами


Потому конструктор без параметров уже есть и перекрывать его нельзя.
Come on, любую структуру можно создать вызвав ктор без параметров:

struct Foo
{
  public Foo(int value) { this.value = value; }
  int value;
}

var f = new Foo();
Re[5]: COM+ и массив Decimal
От: baranovda Российская Империя  
Дата: 26.06.09 12:58
Оценка:
Здравствуйте, Spiceman, Вы писали:


S>Если подскажете, что конкретно надо было указать в MarshalAs, буду благодарен. И хотелось бы еще объяснение получить, почему именно так.


Просто предполагаю, что не лишне подсказать, как мы упаковываем массив структур для маршаллинга

public class Class4
    {
        public void Test4([MarshalAs(UnmanagedType.ByValArray )] decimal[] ddd) { ... }
    }
Re[5]: COM+ и массив Decimal
От: baranovda Российская Империя  
Дата: 26.06.09 13:02
Оценка:
Здравствуйте, Spiceman, Вы писали:

S>Еще десять тысяч вариантов, и я бы сломал клавиатуру.

S>Если подскажете, что конкретно надо было указать в MarshalAs, буду благодарен. И хотелось бы еще объяснение получить, почему именно так.

Default Marshaling for Arrays
http://msdn.microsoft.com/en-us/library/z6cfh6e6(VS.71).aspx#cpcondefaultmarshalingforarraysanchor4
Re[6]: COM+ и массив Decimal
От: Spiceman  
Дата: 26.06.09 13:25
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Просто предполагаю, что не лишне подсказать, как мы упаковываем массив структур для маршаллинга


B>
B>public class Class4
B>    {
B>        public void Test4([MarshalAs(UnmanagedType.ByValArray )] decimal[] ddd) { ... }
B>    }
B>


Не компилецо — Error emitting 'System.Runtime.InteropServices.MarshalAsAttribute' attribute -- 'Specified unmanaged type is only valid on fields.'

Тогда вот остается открытым вопрос, почему, если не наследоваться от интерфейса, то все работает и без ref?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.