XmlSerializer cung cấp FileNotFoundException tại hàm tạo


347

Một ứng dụng tôi đã làm việc bị lỗi khi tôi cố gắng tuần tự hóa các loại.

Một tuyên bố như

XmlSerializer lizer = new XmlSerializer(typeof(MyType));

sản xuất:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  FusionLog=""
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)

Tôi không định nghĩa bất kỳ serial serial đặc biệt nào cho lớp học của mình.

Làm thế nào tôi có thể khắc phục vấn đề này?


5
OK, vì vậy câu hỏi này chỉ là phiên bản C # của tôi về một câu hỏi VB đã được hỏi: stackoverflow.com/questions/294659/ cảm ơn các bạn.
Irwin

1
Sáu năm sau, câu trả lời của @VladV là giải pháp đơn giản nhất và ít ảnh hưởng nhất. Chỉ cần thay đổi trình đơn Generate serialization assemblythả xuống thành "Bật", thay vì "Tự động".
Heliac

@Heliac: Tôi không đồng ý. Nó không phải lúc nào cũng hoạt động. Xin vui lòng xem bình luận của Benoit Blanchon cho câu trả lời của Vlad. Câu trả lời đơn giản nhất đối với tôi là không sử dụng String.Collection trong các tệp cấu hình. Thay vào đó tôi sử dụng: string [] items = Settings.Default.StringofNewlineDeliatedItems.Split (new [] {Môi trường.NewLine});
Andrew Dennison

Câu trả lời:


388

Tin hay không, đây là hành vi bình thường. Một ngoại lệ được ném nhưng được xử lý bởi XmlSerializer, vì vậy nếu bạn bỏ qua nó, mọi thứ sẽ tiếp tục tốt.

Tôi đã thấy điều này rất khó chịu và đã có nhiều phàn nàn về điều này nếu bạn tìm kiếm xung quanh một chút, nhưng từ những gì tôi đã đọc Microsoft không có kế hoạch làm bất cứ điều gì về nó.

Bạn có thể tránh nhận được cửa sổ bật lên Ngoại lệ mọi lúc trong khi gỡ lỗi nếu bạn tắt ngoại lệ cơ hội đầu tiên cho ngoại lệ cụ thể đó. Trong Visual Studio, đi đến Gỡ lỗi -> Ngoại lệ (hoặc nhấn Ctrl+ Alt+ E), Ngoại lệ thời gian chạy ngôn ngữ chung -> System.IO -> System.IO.FileNotFoundException .

Bạn có thể tìm thông tin về một cách khác trong bài đăng trên blog C # XmlSerializer ngoại lệ FileNotFound (thảo luận về công cụ XmlSerializerPreCompiler của Chris Sells ).


162
Một trong những cách có thể để thoát khỏi vấn đề này là chọn tùy chọn "Chỉ mã của tôi" trong Công cụ -> Tùy chọn -> Gỡ lỗi -> Tùy chọn chung.
Frederic

26
@Frederic: Nhận xét này thật tuyệt vời! Tôi đang ngồi đây với một "WTF!?" biểu hiện trên khuôn mặt của tôi, cố gắng tìm ra ngoại lệ giả này và tôi tìm thấy câu hỏi này, với câu trả lời (Đó là lỗi của Microsoft, có gì mới không?), nhưng tôi không muốn tắt xử lý ngoại lệ, vì tôi có thể cần nó cho mã của tôi. A +!
Kumba

27
Tôi nghĩ đề xuất của Hans dưới đây có giá trị hơn - sử dụng một lệnh gọi phương thức khác hoàn toàn không tạo ra ngoại lệ này: XmlSerializer serializer = XmlSerializer.FromTypes (new [] {typeof (MyType)}) [0];
sáng

3
Vấn đề là điều này thất bại trong bài kiểm tra của tôi, vì vậy tôi không thể "bỏ qua" ngoại lệ
Csaba Toth

16
Tôi xin lỗi, nhưng đây là một gợi ý khủng khiếp. FileNotFoundException là một trong những cái phổ biến hơn, theo kinh nghiệm của tôi và việc vô hiệu hóa báo cáo ngoại lệ này chỉ là vấn đề một ngày nào đó trong tương lai. Tốt hơn là bật 'Chỉ mã của tôi' hoặc cho phép tạo các cụm nối tiếp được mô tả bên dưới.
Quarkly

104

Giống như Martin Sherburn nói, đây là hành vi bình thường. Trình xây dựng của XmlSerializer trước tiên cố gắng tìm một tập hợp có tên [YourAssugging] .XmlSerialulators.dll sẽ chứa lớp được tạo để tuần tự hóa loại của bạn. Vì một DLL như vậy chưa được tạo (chúng không phải là mặc định), nên FileNotFoundException sẽ bị ném. Khi điều đó xảy ra, hàm tạo của XmlSerializer bắt ngoại lệ đó và DLL được tạo tự động khi chạy bởi hàm tạo của XmlSerializer (điều này được thực hiện bằng cách tạo tệp nguồn C # trong thư mục% temp% của máy tính của bạn, sau đó biên dịch chúng bằng trình biên dịch C #). Các cấu trúc bổ sung của XmlSerializer cho cùng loại sẽ chỉ sử dụng DLL đã được tạo.

CẬP NHẬT: Bắt đầu từ .NET 4.5, XmlSerializerkhông còn thực hiện tạo mã cũng như không thực hiện biên dịch với trình biên dịch C # để tạo một bộ tuần tự hóa trong thời gian chạy, trừ khi bị buộc phải cài đặt một tệp cấu hình ( useLegacySerializerGeneration ). Thay đổi này loại bỏ sự phụ thuộc vào csc.exevà cải thiện hiệu suất khởi động. Nguồn: .NET Framework 4.5 Readme , phần 1.3.8.1.

Ngoại lệ được xử lý bởi hàm tạo của XmlSerializer. Không cần phải tự làm bất cứ điều gì, bạn chỉ cần nhấp vào 'Tiếp tục' (F5) để tiếp tục thực hiện chương trình của mình và mọi thứ sẽ ổn. Nếu bạn bị làm phiền bởi các ngoại lệ dừng việc thực thi chương trình của bạn và bật lên một trình trợ giúp ngoại lệ, bạn sẽ tắt 'Just My Code' hoặc bạn đã đặt FileNotFoundException để ngắt thực thi khi bị ném, thay vì khi 'Người dùng- chưa xử lý '.

Để bật 'Chỉ mã của tôi', hãy chuyển đến Công cụ >> Tùy chọn >> Gỡ lỗi >> Chung >> Bật Chỉ mã của tôi. Để tắt ngắt thực thi khi ném FileNotFound, hãy truy cập Debug >> Ngoại lệ >> Tìm >> nhập 'FileNotFoundException' >> bỏ chọn hộp kiểm 'Ném' từ System.IO.FileNotFoundException.


+1 cho bản cập nhật: điều này giải thích các hành vi khác nhau khi gỡ lỗi các trường hợp kiểm tra
mbx

3
Bản cập nhật của bạn cho thấy ngoại lệ này không nên xảy ra trong .NET 4.5, nhưng tôi vẫn thấy nó.
Timbo

@Timbo: Tôi không hiểu tại sao bạn sẽ không có ngoại lệ đó với .NET 4.5. Nó vẫn tìm kiếm một tệp và nếu tệp bị thiếu, mộtFileNotFoundException nó sẽ bị ném. Sự khác biệt không nằm ở cách kiểm tra sự tồn tại của tổ hợp, mà là cách tạo ra nó một khi nó xác định rằng nó bị thiếu. Trước đây, nó đã sử dụng việc tạo mã C # bằng văn bản với một cuộc gọi đến trình biên dịch C # để tạo IL. Bắt đầu với .NET 4.5, nó phát ra IL trực tiếp mà không cần sử dụng trình biên dịch.
Allon Guralnek

1
Tôi chỉ muốn MS thực hiện điều này như thể (File.Exists (...)) {Load} khác {Fallback} thay vì thử {Load} bắt {Fallback}. Kiểm soát luồng dựa trên ngoại lệ có mùi khó chịu và làm cho trải nghiệm gỡ lỗi của tôi trở nên khó khăn và dễ vỡ hơn mức cần thiết.
Timbo

1
@Timbo: Một đơn giản File.Exists()có thể không đủ. Xác định vị trí lắp ráp không phải là một việc đơn giản, thời gian chạy tìm kiếm ở một số vị trí và tôi tin rằng hành vi thay đổi theo môi trường (ứng dụng bảng điều khiển so với được lưu trữ trong IIS, v.v.). Tôi đoán những gì nên được thực hiện là một TryLoadAssembly()hoặc một cái gì đó tương tự.
Allon Guralnek

63

Trong thuộc tính dự án Visual Studio (trang "Build", nếu tôi nhớ lại đúng), có một tùy chọn cho biết "tạo lắp ráp nối tiếp". Hãy thử bật nó cho một dự án tạo ra [Chứa hội MyType] .


4
Đồng thời xem stackoverflow.com/a/8798289/1164966 nếu lắp ráp nối tiếp vẫn không được tạo bởi Visual Studio.
Benoit Blanchon

Câu trả lời hay nhất, rõ ràng nhất, súc tích! Tôi ước tôi có thể bỏ phiếu một lần nữa quá!
John Zabroski

59

Có một cách giải quyết cho điều đó. Nếu bạn dùng

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];

cần tránh ngoại lệ đó Điều này làm việc cho tôi.

CẢNH BÁO: Không sử dụng nhiều lần, nếu không bạn sẽ bị rò rỉ bộ nhớ

Bạn sẽ rò rỉ bộ nhớ như điên nếu bạn sử dụng phương pháp này để tạo các thể hiện XmlSerializercho cùng loại nhiều lần!

Điều này là do phương thức này bỏ qua bộ nhớ đệm tích hợp được cung cấp XmlSerializer(type)và các hàm XmlSerializer(type, defaultNameSpace)tạo (tất cả các hàm tạo khác cũng bỏ qua bộ đệm).

Nếu bạn sử dụng bất kỳ phương pháp nào để tạo XmlSerializer không thông qua hai hàm tạo này, bạn phải thực hiện bộ nhớ đệm của riêng mình hoặc bạn sẽ bị xuất huyết bộ nhớ.


44
CẢNH BÁO: Bạn sẽ rò rỉ bộ nhớ như điên nếu bạn sử dụng phương pháp này để tạo các phiên bản XmlSerializercho cùng loại nhiều lần! Điều này là do phương thức này bỏ qua bộ nhớ đệm tích hợp được cung cấp XmlSerializer(type)và các hàm XmlSerializer(type, defaultNameSpace)tạo (tất cả các hàm tạo khác cũng bỏ qua bộ đệm). Nếu bạn sử dụng bất kỳ phương pháp nào để tạo một phương thức XmlSerializerkhông thông qua hai hàm tạo này, bạn phải thực hiện bộ nhớ đệm của riêng mình hoặc bạn sẽ xuất huyết bộ nhớ.
Allon Guralnek

4
@ ALLonGuralnek Tôi sẽ bị nguyền rủa ... bạn hoàn toàn chính xác; đào sâu hơn thông qua Reflector cho thấy rằng mặc dù nó kiểm tra bộ đệm, nhưng nó sẽ làm như vậy sau khi tạo cụm nối tiếp! Wtf?!?
JerKimball


3
@JerKimball: Trang đó không thực sự nói dối. Khi bạn phát hiện ra, FromTypessẽ xuất hiện để điền vào bộ đệm. Vì vậy, nó nên là một cách hợp lệ để làm nóng XmlSerializerbộ đệm trống trong một câu lệnh (như bài báo gợi ý), nhưng là một cách thực sự tồi để lấy bất cứ thứ gì từ nó (chỉ nên được thực hiện thông qua các hàm tạo đơn giản nhất). Trong mọi trường hợp, tôi không biết đó là một lỗi, tôi luôn nghĩ bất cứ điều gì rò rỉ được cho là rò rỉ (như các nhà XmlSerializerxây dựng tiên tiến hơn ). Tôi thậm chí sẽ không cân nhắc sử dụng FromTypes()vì bạn có thể làm types.Select(t => new XmlSerializer(t)).
Allon Guralnek

2
@ ALLonGuralnek Khía cạnh FromTypeskhông sử dụng có sức hấp dẫn của nó - ngay cả khi các ngoại lệ được ném đều bị bắt, đó là một hoạt động có giá trị; phương pháp 'bộ nhớ cache theo cách riêng của bạn' dường như là cách giải quyết duy nhất, vì cách khắc phục được hỗ trợ chính thức duy nhất có vẻ nằm trong một hội đồng dựa trên web tối nghĩa. (chỉnh sửa: thẳng thắn, tôi là tất cả để chuyển mọi thứ sang hợp đồng dữ liệu :))
JerKimball

22

Tôi gặp vấn đề chính xác này và không thể giải quyết vấn đề này bằng bất kỳ giải pháp nào được đề cập.

Rồi cuối cùng tôi cũng tìm được giải pháp. Dường như serializer không chỉ cần loại, mà cả các loại lồng nhau. Thay đổi điều này:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

Về điều này:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());

Đã khắc phục sự cố cho tôi. Không có ngoại lệ hoặc bất cứ điều gì.


8
Điều này làm việc cho tôi. Sử dụng .Net4.0 định dạng làvar xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
user3161729

1
Cái này cũng có tác dụng với tôi. Nhưng nó chỉ có vẻ là cần thiết khi tuần tự hóa, không phải khi khử lưu huỳnh. Có lẽ điều đó có ý nghĩa, có thể nó không.
SteveCinq

2
Điều này cũng tạo ra rò rỉ bộ nhớ, nếu chạy rất nhiều lần.
Volodymyr Kotylo

9

Giải pháp của tôi là đi thẳng vào sự phản chiếu để tạo ra serializer. Điều này bỏ qua việc tải tập tin lạ gây ra ngoại lệ. Tôi đã đóng gói cái này trong một hàm trợ giúp cũng đảm nhiệm việc lưu trữ bộ tuần tự.

private static readonly Dictionary<Type,XmlSerializer> _xmlSerializerCache = new Dictionary<Type, XmlSerializer>();

public static XmlSerializer CreateDefaultXmlSerializer(Type type) 
{
    XmlSerializer serializer;
    if (_xmlSerializerCache.TryGetValue(type, out serializer))
    {
        return serializer;
    }
    else
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(type, null, null);
        serializer = new XmlSerializer(mapping);
        return _xmlSerializerCache[type] = serializer;
    }
}

Có 2 vấn đề ở đây - đầu tiên mã của bạn không an toàn cho luồng và thứ hai (quan trọng hơn) bạn đang cố gắng sao chép những gì thời gian chạy .net đã làm (dựa trên ctor bạn đang sử dụng). tức là không cần mã này
Dave Black

@DaveBlack: Có, câu trả lời của tứ giác với bộ nhớ đệm cho Đồng thời Từ điển sẽ tốt hơn
d - b

@db Điểm thứ 2 của tôi là bộ nhớ đệm thậm chí không cần thiết - miễn là bạn đang sử dụng một trong 2 bộ đệm mà khung lưu trữ (OP đang sử dụng cái đầu tiên). Từ MSDN: Để tăng hiệu suất, cơ sở hạ tầng tuần tự hóa XML tự động tạo ra các cụm để tuần tự hóa và giải tuần tự hóa các loại được chỉ định. Khung tìm và tái sử dụng các hội đồng đó. Hành vi này chỉ xảy ra khi sử dụng các công cụ sau: XmlSerializer.XmlSerializer (Loại) XmlSerializer.XmlSerializer (Loại, Chuỗi) Tham khảo: msdn.microsoft.com/en-us/l Library / do
Dave Black

@DaveBlack: Có, nhưng các nhà xây dựng này ném và bắt ngoại lệ trong nội bộ ngay cả khi việc sử dụng hoàn toàn hợp lệ. Điều này là xấu, và đây là lý do tại sao OP đặt câu hỏi ngay từ đầu.
d - b

@db Đúng, nhưng điều tôi muốn nói (nhưng không rõ ràng - lời xin lỗi của tôi) là dòng duy nhất của bạn cần thiết là 3 dòng đầu tiên trong điều kiện khác.
Dave Black

8

Để tránh ngoại lệ, bạn cần làm hai việc:

  1. Thêm một thuộc tính cho lớp được tuần tự hóa (tôi hy vọng bạn có quyền truy cập)
  2. Tạo tập tin tuần tự hóa với sgen.exe

Thêm thuộc tính System.Xml.Serialization.XmlSerializerAssugging vào lớp của bạn. Thay thế 'MyAssugging' bằng tên của hội đồng nơi MyClass đang ở.

[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{

}

Tạo tập tin tuần tự hóa bằng tiện ích sgen.exe và triển khai nó với tập hợp của lớp.

'sgen.exe MyAss lanh.dll' sẽ tạo tệp MyAssugging.XmlSerialulators.dll

Hai thay đổi này sẽ khiến .net trực tiếp tìm thấy lắp ráp. Tôi đã kiểm tra nó và nó hoạt động trên .NET framework 3.5 với Visual Studio 2008


Ok, và nó đã thất bại nếu không có những thay đổi này, và nếu vậy, tại sao?
John Saunders

1
Tôi không thể tìm thấy lý do tại sao dự án của tôi, 4.0 trong VS2012, đột nhiên bắt đầu thất bại. "Bỏ qua" lỗi không phải là một tùy chọn, vì nó xảy ra mỗi khi tôi cố gắng truy cập Active Directory; do đó bỏ qua có nghĩa là không xác thực. Tôi vẫn rất thất vọng vì VS2012 sẽ không tự động tạo DLL tuần tự hóa đúng cách. Tuy nhiên, các bước này cung cấp giải pháp hoàn hảo.
sfuqua

6

Ngoại lệ này cũng có thể bị bẫy bởi một trợ lý gỡ lỗi được quản lý (MDA) được gọi là BindingFailure.

MDA này rất hữu ích nếu ứng dụng của bạn được thiết kế để gửi cùng với các hội đồng tuần tự hóa trước khi xây dựng. Chúng tôi làm điều này để tăng hiệu suất cho ứng dụng của chúng tôi. Nó cho phép chúng tôi đảm bảo rằng các hội đồng tuần tự dựng sẵn đang được xây dựng đúng theo quy trình xây dựng của chúng tôi và được ứng dụng tải mà không cần xây dựng lại khi đang di chuyển.

Nó thực sự không hữu ích ngoại trừ trong kịch bản này, vì như các áp phích khác đã nói, khi một lỗi liên kết bị bẫy bởi hàm tạo của Trình tạo tuần tự, lắp ráp nối tiếp được xây dựng lại khi chạy. Vì vậy, bạn thường có thể tắt nó.


6

Chức năng XmlSerializer.FromTypes không ném ngoại lệ, nhưng nó làm rò rỉ bộ nhớ. Đó là lý do tại sao bạn cần lưu trữ bộ tuần tự như vậy cho mọi loại để tránh rò rỉ bộ nhớ cho mọi phiên bản được tạo.

Tạo nhà máy XmlSerializer của riêng bạn và sử dụng nó một cách đơn giản:

XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(MyType));

Nhà máy có vẻ như:

public static class XmlSerializerFactoryNoThrow
{
    public static Dictionary<Type, XmlSerializer> _cache = new Dictionary<Type, XmlSerializer>();

    private static object SyncRootCache = new object();        

    /// <summary>
    /// //the constructor XmlSerializer.FromTypes does not throw exception, but it is said that it causes memory leaks
    /// http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor
    /// That is why I use dictionary to cache the serializers my self.
    /// </summary>
    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            //constructor XmlSerializer.FromTypes does not throw the first chance exception           
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            //serializer = XmlSerializerFactoryNoThrow.Create(type);
        }

        lock (SyncRootCache)
        {
            _cache[type] = serializer;
        }
        return serializer;
    }       
}

Phiên bản phức tạp hơn mà không có khả năng rò rỉ bộ nhớ (vui lòng ai đó xem lại mã):

    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            lock (SyncRootCache)
            {
                if (_cache.TryGetValue(type, out serializer))
                    return serializer;
            }
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            lock (SyncRootCache)
            {
                _cache[type] = serializer;
            }
        }          
        return serializer;
    }       
}

Thay vào đó, bạn nên sử dụng đồng thời. Mã này có thể bế tắc.
Behrooz

Làm thế nào nó có thể bế tắc nếu tất cả quản lý với từ điển nằm trong phần khóa?
Tomas Kubes

Xin lỗi, tôi nhận được những lời nhầm lẫn. Ý tôi là nó có thể Chèn một mục nhiều lần. bởi vì có một khoảng cách giữa khi nó kiểm tra sự tồn tại và khi nó chèn vào. từ điển đồng thời sử dụng một số loại khóa hai pha (túi [0] và sau đó là túi [băm]]) và giữ một tham chiếu đến túi phải chèn / chứa vật phẩm bạn đang làm việc. Nó nhanh hơn, an toàn hơn và sạch hơn.
Behrooz

Có và không. Bạn đúng rằng có thể xảy ra rằng trong cùng một thời điểm, một serializer cùng loại sẽ được tạo trên hai luồng song song và sau đó được thêm vào từ điển hai lần. Trong trường hợp như vậy, phần chèn thứ hai sẽ chỉ thay thế phần thứ nhất, nhưng phần khóa đảm bảo an toàn cho luồng và nhược điểm chung là rò rỉ bộ nhớ nhỏ. Đây là tối ưu hóa hiệu suất, vì bạn không muốn luồng một với Trình tuần tự loại A chờ bị chặn bởi luồng hai với trình tuần tự loại B trong kịch bản thực.
Tomas Kubes

Tôi có thể tưởng tượng giải pháp có thể còn tốt hơn (không bị rò rỉ bộ nhớ lý thuyết), nhưng phức tạp hơn.
Tomas Kubes

3

Mặt khác, việc khắc phục lỗi biên dịch rất phức tạp. Các vấn đề này tự biểu hiện trong FileNotFoundException với thông báo:

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
   at System.Reflection.Assembly.nLoad( ... )
   at System.Reflection.Assembly.InternalLoad( ... )
   at System.Reflection.Assembly.Load(...)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() 

Bạn có thể tự hỏi một tập tin không tìm thấy ngoại lệ có liên quan gì đến việc khởi tạo một đối tượng serializer, nhưng hãy nhớ: hàm tạo ghi các tệp C # và cố gắng biên dịch chúng. Ngăn xếp cuộc gọi của ngoại lệ này cung cấp một số thông tin tốt để hỗ trợ sự nghi ngờ đó. Ngoại lệ xảy ra trong khi XmlSerializer cố tải một cụm được tạo bởi CodeDOM gọi phương thức System.Reflection.Ass lanh.Load. Ngoại lệ không cung cấp một lời giải thích về lý do tại sao lắp ráp mà XmlSerializer được cho là tạo ra không có mặt. Nói chung, lắp ráp không có mặt vì quá trình biên dịch thất bại, điều này có thể xảy ra bởi vì, trong những trường hợp hiếm hoi, các thuộc tính tuần tự hóa tạo ra mã mà trình biên dịch C # không thể biên dịch.

Lưu ý Lỗi này cũng xảy ra khi XmlSerializer chạy trong tài khoản hoặc môi trường bảo mật không thể truy cập thư mục tạm thời.

Nguồn : http://msdn.microsoft.com/en-us/l Library / aa302290.aspx


ông đã không xác định rằng điều này xảy ra trong thời gian chạy. Một điều khác tôi có thể nghĩ là có lẽ bạn có xung đột không gian tên / lớp. Tên đầy đủ của MyType của bạn là gì?
Zyphrax

Vâng, tôi đã kiểm tra liên kết của bạn, thông tin về các nhà xây dựng, mặc dù hữu ích, không phải là thứ tôi cần.
Irwin

5
@SpaceghostAl Bạn có thể biên dịch khi chạy. Và đó là những gì XmlSerializer làm. Nó tự động xây dựng trong thời gian chạy một tập hợp (de) tuần tự hóa XML cho loại cụ thể. Vì lý do gì quá trình này thất bại cho OP. Có thể do các vấn đề về quyền, ví dụ như trên một thư mục tạm thời. (Có thể ngớ ngẩn như hết dung lượng đĩa.)
nos

Bạn có chắc về điều này? Tôi khá chắc chắn rằng các công cụ tuần tự hóa được biên dịch thành một hội đồng với tên YourAssuggingName.XmlSerialulators.dll trong quá trình xây dựng , không được biên dịch khi chạy. Điều này có thể thất bại vì tất cả các loại lý do, ít nhất là tất cả các quyền NTFS trong thư mục triển khai.
tomfanning

1
Tôi ước tôi có thể nâng cấp điều này nhiều lần. Lưu ý của bạn về việc tài khoản không thể truy cập thư mục tạm thời đã kích hoạt câu trả lời cho tôi. Khi tôi đã thêm tài khoản dịch vụ của mình vào nhóm quản trị viên trên máy chủ, nó mới hoạt động. Cảm ơn bạn!
Bob Horn

2

Trong thuộc tính dự án Visual Studio có một tùy chọn cho biết "tạo lắp ráp nối tiếp". Hãy thử bật nó cho một dự án tạo ra [Chứa hội MyType].


1

Một lớp tùy chỉnh để nối tiếp:

[Serializable]
public class TestClass
{
    int x = 2;
    int y = 4;
    public TestClass(){}
    public TestClass(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int TestFunction()
    {
        return x + y;
    }
}

Tôi đã đính kèm đoạn mã. Có lẽ điều này có thể giúp bạn ra ngoài.

static void Main(string[] args)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));

    MemoryStream memoryStream = new MemoryStream();
    XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

    TestClass domain = new TestClass(10, 3);
    xmlSerializer.Serialize(xmlWriter, domain);
    memoryStream = (MemoryStream)xmlWriter.BaseStream;
    string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray());

    TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString);

    Console.WriteLine(xmlDomain.TestFunction().ToString());
    Console.ReadLine();
}

2
-1 không sử dụng các khối để ngăn rò rỉ tài nguyên và sử dụng XmlTextWriter.
John Saunders

ok đồng ý, nhưng tôi vẫn sử dụng XmlSerializer xmlSerializer = new XmlSerializer (typeof (TestClass)); nhưng tôi không nhận được Ngoại lệ nói.
shahjapan

1

Tôi đã có một vấn đề tương tự, và bỏ qua ngoại lệ không làm việc cho tôi. Mã của tôi đã gọi cấu hình của NServiceBusConfigure.With(...).XmlSerializer()...

Điều cố định nó cho tôi là thay đổi nền tảng cho dự án của tôi.

  1. Chuyển đến Build \ Trình quản lý cấu hình ...
  2. Tìm dự án của bạn và thay đổi Nền tảng (trong trường hợp của tôi từ x86 sang CPU bất kỳ)

1

Chỉ là tài liệu tham khảo. Lấy từ câu trả lời và nhận xét của DB, tôi đã đưa ra giải pháp này gần với giải pháp DB. Nó hoạt động tốt trong tất cả các trường hợp của tôi và nó là chủ đề an toàn. Tôi không nghĩ rằng việc sử dụng một Đồng thời Từ điển sẽ ổn.

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace HQ.Util.General
{
    public class XmlSerializerHelper
    {
        private static readonly Dictionary<Type, XmlSerializer> _dictTypeToSerializer = new Dictionary<Type, XmlSerializer>();

        public static XmlSerializer GetSerializer(Type type)
        {
            lock (_dictTypeToSerializer)
            {
                XmlSerializer serializer;
                if (! _dictTypeToSerializer.TryGetValue(type, out serializer))
                {
                    var importer = new XmlReflectionImporter();
                    var mapping = importer.ImportTypeMapping(type, null, null);
                    serializer = new XmlSerializer(mapping);
                    return _dictTypeToSerializer[type] = serializer;
                }

                return serializer;
            }
        }
    }
}

Sử dụng:

        if (File.Exists(Path))
        {
            using (XmlTextReader reader = new XmlTextReader(Path))
            {
                // XmlSerializer x  = new XmlSerializer(typeof(T));
                var x = XmlSerializerHelper.GetSerializer(typeof(T));

                try
                {
                    options = (OptionsBase<T>)x.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    Log.Instance.AddEntry(LogType.LogException, "Unable to open Options file: " + Path, ex);
                }
            }
        }

0

Kiểu của bạn có thể tham chiếu các tập hợp khác không thể tìm thấy trong GAC cũng như trong thư mục bin cục bộ của bạn ==> ...

"hoặc một trong các phụ thuộc của nó. Hệ thống không thể tìm thấy tệp được chỉ định"

Bạn có thể đưa ra một ví dụ về loại bạn muốn nối tiếp?

Lưu ý: Đảm bảo rằng loại của bạn thực hiện Nối tiếp.


0

Tôi đã nhận được cùng một lỗi, và đó là do loại tôi đang cố gắng giải tuần tự hóa không có một hàm tạo không tham số mặc định . Tôi đã thêm một constructor, và nó bắt đầu làm việc.


0

Tôi gặp vấn đề tương tự cho đến khi tôi sử dụng công cụ của bên thứ 3 để tạo Class từ XSD và nó đã hoạt động! Tôi phát hiện ra rằng công cụ này đã thêm một số mã bổ sung ở đầu lớp. Khi tôi thêm cùng mã này vào đầu lớp ban đầu của tôi, nó đã hoạt động. Đây là những gì tôi đã thêm ...

#pragma warning disable
namespace MyNamespace
{
  using System;
  using System.Diagnostics;
  using System.Xml.Serialization;
  using System.Collections;
  using System.Xml.Schema;
  using System.ComponentModel;
  using System.Xml;
  using System.Collections.Generic;

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
  [System.SerializableAttribute()]
  [System.Diagnostics.DebuggerStepThroughAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
  public partial class MyClassName
  {
  ...

0

Nhìn thấy rất nhiều khuyến nghị để sử dụng một ConcurrentDictionary, nhưng không có ví dụ chắc chắn về nó, vì vậy tôi sẽ ném chiếc mũ của mình vào cuộc đua giải pháp này. Tôi không phải là nhà phát triển an toàn luồng, vì vậy nếu mã này không vững chắc, vui lòng lên tiếng vì lợi ích của những người theo dõi.

public static class XmlSerializerHelper
{
    private static readonly ConcurrentDictionary<Type, XmlSerializer> TypeSerializers = new ConcurrentDictionary<Type, XmlSerializer>();

    public static XmlSerializer GetSerializer(Type type)
    {
        return TypeSerializers.GetOrAdd(type,
        t =>
        {
            var importer = new XmlReflectionImporter();
            var mapping = importer.ImportTypeMapping(t, null, null);
            return new XmlSerializer(mapping);
        });
    }
}

Tôi đã thấy các bài viết khác liên quan ConcurrentDictionaryLazytải giá trị. Tôi không chắc có liên quan ở đây hay không, nhưng đây là mã cho điều đó:

private static readonly ConcurrentDictionary<Type, Lazy<XmlSerializer>> TypeSerializers = new ConcurrentDictionary<Type, Lazy<XmlSerializer>>();

public static XmlSerializer GetSerializer(Type type)
{
    return TypeSerializers.GetOrAdd(type,
    t =>
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(t, null, null);
        var lazyResult = new Lazy<XmlSerializer>(() => new XmlSerializer(mapping), LazyThreadSafetyMode.ExecutionAndPublication);
        return lazyResult;
    }).Value;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.